home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / games / egavga / tads2doc.arj / DITCH.T < prev    next >
Text File  |  1992-11-12  |  115KB  |  3,882 lines

  1. /*  Copyright (c) 1990 by Michael J. Roberts.  All Rights Reserved. */
  2. /*
  3.     Ditch Day Drifter
  4.     Interactive Fiction by Michael J. Roberts.
  5.     
  6.     Developed with TADS: The Text Adventure Development System.
  7.     
  8.     This game is a sample TADS source file.  It demonstrates many of the
  9.     features of TADS.  The TADS language is fully documented in the TADS
  10.     Author's Manual, which is available only to registered owners of the
  11.     Text Adventure Development System.  While this file is intended to
  12.     illustrate most of the important features of TADS, it is provided
  13.     partially for evaluation purposes, to help you to make an informed
  14.     decision as to whether TADS suits your needs, and to partially to
  15.     complement the TADS Author's Manual; this file is not intended to be
  16.     a substitute for the full documentation of the system.  If you find
  17.     that TADS is useful to you, please register your copy.
  18.     
  19.     Please read LICENSE.DOC for information about using and copying this
  20.     file, and about registering your copy of TADS.
  21. */
  22.  
  23. /*
  24.  *   First, insert the file containing the standard adventure definitions.
  25.  */
  26. #include <adv.t>
  27.  
  28. /*
  29.  *   Pre-declare some functions, so the compiler knows they are functions.
  30.  *   (This is only really necessary when a function will be referenced
  31.  *   as a daemon or fuse before it is defined; however, it doesn't hurt
  32.  *   anything to pre-declare all of them.)
  33.  */
  34. die: function;
  35. scoreRank: function;
  36. init: function;
  37. terminate: function;
  38. pardon: function;
  39. sleepDaemon: function;
  40. eatDaemon: function;
  41. darkTravel: function;
  42.  
  43. /* provide a preparse function, but don't bother doing anything */
  44. preparse: function(cmd)
  45. {
  46.     return(true);
  47. }
  48.  
  49. /* likewise, provide a parseError function that doesn't do anything */
  50. parseError: function(num, str)
  51. {
  52.     return(nil);
  53. }
  54.  
  55. /*
  56.  *   The die() function is called when the player dies.  It tells the
  57.  *   player how well he has done (with his score), and asks if he'd
  58.  *   like to start over (the alternative being quitting the game).
  59.  */
  60. die: function
  61. {
  62.     "\b*** You have died ***\b";
  63.     scoreRank();
  64.  
  65.     /*
  66.      *   Check if the player (Me) purchased insurance.  If so, issue
  67.      *   an appropriate message.
  68.      */
  69.     if ( Me.isinsured )
  70.         "\bI'm sure that Lloyd is even now paying out a big lump sum for
  71.     your early demise. However, that is of little use to you now. ";
  72.  
  73.     /*
  74.      *   Tell the user the options available, and then ask for some
  75.      *   input.  Keep asking until we get something we recognize.
  76.      */
  77.     "\bYou may restore a saved game, start over, undo the
  78.     last move, or quit. ";
  79.     while ( 1 )
  80.     {
  81.         local resp;
  82.  
  83.     "\nPlease enter RESTORE, RESTART, UNDO, or QUIT: >";
  84.         resp := upper(input());     /* get input, convert to uppercase */
  85.         if ( resp = 'RESTORE' )
  86.     {
  87.         resp := askfile( 'File to restore' );       /* find filename */
  88.         if ( resp = nil ) "Restore failed. ";
  89.         else if ( restore( resp )) "Restore failed. ";
  90.         else
  91.         {
  92.             /*
  93.          *   We've successfully restored a game.  Reset the status
  94.          *   line's score/turn counter, and resume play.
  95.          */
  96.             setscore( global.score, global.turnsofar );
  97.         abort;
  98.         }
  99.     }
  100.         else if ( resp = 'RESTART' )
  101.     {
  102.         /*
  103.          *   We're going to start over.  Reset the status line's
  104.          *   score/turn counter and start from the beginning.
  105.          */
  106.         setscore( 0, 0 );
  107.             restart();
  108.     }
  109.     else if ( resp = 'UNDO' )
  110.     {
  111.         if (undo())
  112.         {
  113.         "(Undoing one command)\b";
  114.         Me.location.lookAround(true);
  115.         setscore(global.score, global.turnsofar);
  116.         abort;
  117.         }
  118.         else
  119.         "Sorry, no undo information is available.";
  120.     }
  121.     else if ( resp = 'QUIT' )
  122.         {
  123.         /*
  124.          *   We're quitting the game.  Do any final activity necessary,
  125.          *   and exit.
  126.          */
  127.         terminate();
  128.             quit();
  129.         abort;
  130.         }
  131.     }
  132. }
  133.  
  134. /*
  135.  *   The scoreRank() function displays how well the player is doing.
  136.  *   In addition to displaying the numerical score and number of turns
  137.  *   played so far, we'll classify the score with a rank such as "sophomore."
  138.  *
  139.  *   Note that "global.maxscore" defines the maximum number of points
  140.  *   possible in the game.
  141.  */
  142. scoreRank: function
  143. {
  144.     local s;
  145.     
  146.     s := global.score;
  147.     
  148.     "In a total of "; say( global.turnsofar );
  149.     " turns, you have achieved a score of ";
  150.     say( s ); " points out of a possible "; say( global.maxscore );
  151.     ", which gives you a rank of ";
  152.     
  153.     if ( s < 10 ) "high-school hopeful";
  154.     else if ( s < 25 ) "freshman";
  155.     else if ( s < 40 ) "sophomore";
  156.     else if ( s < 60 ) "junior";
  157.     else if ( s < global.maxscore ) "senior";
  158.     else "graduate";
  159.     
  160.     ". ";
  161. }
  162.  
  163. /*
  164.  *   The init() function is run at the very beginning of the game.
  165.  *   We display some introductory text, then move the player (Me) to the
  166.  *   initial location and set up some background activity.
  167.  */
  168. init: function
  169. {
  170.     "\tYou wake up to the sound of voices in the hall. You are confused for
  171.     a moment; it's only 8 AM, far too early for anyone to be getting up.
  172.     Then, it dawns on you: it's ditch day here at the fictitious California
  173.     Institute of Technology in the mythical city of Pasadena, California.
  174.     Ditch Day, that strange tradition wherein seniors bar their doors with
  175.     various devices and underclassmen attempt to defeat these devices (for
  176.     no other apparent reason than that the devices are there), has arrived.\b";
  177.     
  178.     version.sdesc;                // display the game's name and version number
  179.     "\b";
  180.     
  181.     setdaemon( turncount, nil );               // start the turn counter daemon
  182.     setdaemon( sleepDaemon, nil );                    // start the sleep daemon
  183.     setdaemon( eatDaemon, nil );                     // start the hunger daemon
  184.     Me.location := startroom;                // move player to initial location
  185.     startroom.lookAround( true );                    // show player where he is
  186.     startroom.isseen := true;
  187. }
  188.  
  189. /*
  190.  *   preinit() is called after compiling the game, before it is written
  191.  *   to the binary game file.  It performs all the initialization that can
  192.  *   be done statically before storing the game in the file, which speeds
  193.  *   loading the game, since all this work has been done ahead of time.
  194.  *
  195.  *   This routine puts all lamp objects (those objects with islamp = true) into
  196.  *   the list global.lamplist.  This list is consulted when determining whether
  197.  *   a dark room contains any light sources.
  198.  */
  199. preinit: function
  200. {
  201.     local o;
  202.     
  203.     global.lamplist := [];
  204.     o := firstobj(lightsource);
  205.     while( o <> nil )
  206.     {
  207.         if ( o.islamp ) global.lamplist := global.lamplist + o;
  208.         o := nextobj(o, lightsource);
  209.     }
  210. }
  211.  
  212. /*
  213.  *   The terminate() function is called just before the game ends.  We
  214.  *   just display a good-bye message.
  215.  */
  216. terminate: function
  217. {
  218.     "\bThanks for participating in Ditch Day!\n";
  219. }
  220.  
  221. /*
  222.  *   The pardon() function is called any time the player enters a blank
  223.  *   line.
  224.  */
  225. pardon: function
  226. {
  227.     "I beg your pardon? ";
  228. }
  229.  
  230. /*
  231.  *   This function is a daemon, started by init(), that monitors how long
  232.  *   it has been since the player slept.  It provides warnings for a while
  233.  *   before the player gets completely exhausted, and causes the player
  234.  *   to pass out and sleep when it has been too long.  The only penalty
  235.  *   exacted if the player passes out is that he drops all his possessions.
  236.  *   Some games might also wish to consider the effects of several hours
  237.  *   having passed; for example, the time-without-food count might be
  238.  *   increased accordingly.
  239.  */
  240. sleepDaemon: function( parm )
  241. {
  242.     local a, s;
  243.  
  244.     global.awakeTime := global.awakeTime + 1;
  245.     a := global.awakeTime;
  246.     s := global.sleepTime;
  247.  
  248.     if ( a = s or a = s+10 or a = s+20 )
  249.         "\bYou're feeling a bit drowsy; you should find a
  250.         comfortable place to sleep. ";
  251.     else if ( a = s+25 or a = s+30 )
  252.         "\bYou really should find someplace to sleep soon, or
  253.         you'll probably pass out from exhaustion. ";
  254.     else if ( a >= s+35 )
  255.     {
  256.       global.awakeTime := 0;
  257.       if ( Me.location.isbed or Me.location.ischair )
  258.       {
  259.         "\bYou find yourself unable to stay awake any longer.
  260.         Fortunately, you are ";
  261.         if ( Me.location.isbed ) "on "; else "in ";
  262.         Me.location.adesc; ", so you gently slip off into
  263.         unconsciousness.
  264.         \b* * * * *
  265.         \bYou awake some time later, feeling refreshed. ";
  266.       }
  267.       else
  268.       {
  269.         local itemRem, thisItem;
  270.         "\bYou find yourself unable to stay awake any longer.
  271.         You pass out, falling to the ground.
  272.         \b* * * * *
  273.         \bYou awaken, feeling somewhat the worse for wear.
  274.         You get up and dust yourself off. ";
  275.         itemRem := Me.contents;
  276.         while (car( itemRem ))
  277.         {
  278.             thisItem := car( itemRem );
  279.             if ( not thisItem.isworn ) thisItem.moveInto( Me.location );
  280.         itemRem := cdr( itemRem );
  281.         }
  282.       }
  283.     }
  284. }
  285.  
  286. /*
  287.  *   This function is a daemon, set running by init(), which monitors how
  288.  *   long it has been since the player has had anything to eat.  It will
  289.  *   provide warnings for some time prior to the player's expiring from
  290.  *   hunger, and will kill the player if he should go too long without
  291.  *   heeding these warnings.
  292.  */
  293. eatDaemon: function( parm )
  294. {
  295.     local e, l;
  296.  
  297.     global.lastMealTime := global.lastMealTime + 1;
  298.     e := global.eatTime;
  299.     l := global.lastMealTime;
  300.  
  301.     if ( l = e or l = e+5 or l = e+10 )
  302.         "\bYou're feeling a bit peckish. Perhaps it would be a good
  303.         time to find something to eat. ";
  304.     else if ( l = e+15 or l = e+20 or l = e+25 )
  305.         "\bYou're feeling really hungry. You should find some food
  306.         soon or you'll pass out from lack of nutrition. ";
  307.     else if ( l=e+30 or l = e+35 )
  308.         "\bYou really can't go much longer without food. ";
  309.     else if ( l >= e+40 )
  310.     {
  311.         "\bYou simply can't go on any longer without food. You perish from
  312.         lack of nutrition. ";
  313.         die();
  314.     }
  315. }
  316.  
  317. /*
  318.  *   The numObj object is used to convey a number to the game whenever
  319.  *   the player uses a number in his command.  For example, "turn dial
  320.  *   to 621" results in an indirect object of numObj, with its "value"
  321.  *   property set to 621.  Just pick up the default definition from adv.t.
  322.  */
  323. numObj: basicNumObj;
  324.  
  325. /*
  326.  *   strObj works like numObj, but for strings.  So, a player command of
  327.  *     type "hello" on the keyboard
  328.  *   will result in a direct object of strObj, with its "value" property
  329.  *   set to the string 'hello'.
  330.  *
  331.  *   Note that, because a string direct object is used in the save, restore,
  332.  *   and script commands, this object must handle those commands.  We'll just
  333.  *   pick up the default definition from adv.t.
  334.  */
  335. strObj: basicStrObj;
  336.  
  337. /*
  338.  *   The "global" object is the dumping ground for any data items that
  339.  *   don't fit very well into any other objects.
  340.  */
  341. global: object
  342.     turnsofar = 0                            // no turns have transpired so far
  343.     score = 0                            // no points have been accumulated yet
  344.     maxscore = 80                                     // maximum possible score
  345.     verbose = nil                             // we are currently in TERSE mode
  346.     awakeTime = 0               // time that has elapsed since the player slept
  347.     sleepTime = 600     // interval between sleeping times (longest time awake)
  348.     lastMealTime = 0              // time that has elapsed since the player ate
  349.     eatTime = 250         // interval between meals (longest time without food)
  350.     lamplist = []              // list of all known light providers in the game
  351. ;
  352.  
  353. /*
  354.  *   The "version" object defines, via its "sdesc" property, the name and
  355.  *   version number of the game.
  356.  */
  357. version: object
  358.     sdesc = "Ditch Day Drifter
  359.      \nInteractive Fiction by Michael J.\ Roberts
  360.      \bRelease 1.0
  361.      \nCopyright (c) 1990 by Michael J.\ Roberts. All Rights Reserved.
  362.      \nDeveloped with TADS: The Text Adventure Development System. "
  363. ;
  364.  
  365. /*
  366.  *   "Me" is the player's actor.  Pick up the default definition, basicMe,
  367.  *   from "adv.t".
  368.  */
  369. Me: basicMe
  370. ;
  371.  
  372. /*
  373.  *   darkTravel() is called whenever the player attempts to move from a dark
  374.  *   location into another dark location.  We don't do much of anything;
  375.  *   some games might impose a probability of walking into the slavering
  376.  *   jaws of a grue, whatever that might be.
  377.  */
  378. darkTravel: function
  379. {
  380.     "You stumble around in the dark, and don't get anywhere. ";
  381. }
  382.  
  383. /*
  384.  *   The player will start in the room called "startroom", by virtue
  385.  *   of being placed there by the "init" function.
  386.  *
  387.  *   All rooms have an sdesc (short description), which is displayed on
  388.  *   the status line and on entry to the room (even if the room has been
  389.  *   seen before).  In addition, the ldesc (long description) is printed
  390.  *   when the player enters the room for the first time or types "look."
  391.  *   Directions (north, south, east, west, ne, nw, se, sw, in, out)
  392.  *   specify where the exits go.  If a direction is not specified, no
  393.  *   exit is in that direction.
  394.  */
  395. startroom: room
  396.     sdesc = "Room 3"                                // short description
  397.     ldesc = "This is your room. You live a fairly austere life, being a
  398.      poor college student. The only notable features are the bed
  399.      (unmade, of course) and a small wooden desk.  An exit is west. "
  400.     west = alley1                                   // room that lies west
  401.     out = alley1                                    // the exit
  402. ;
  403.  
  404. /*
  405.  *   The desk is a surface, which means you can put stuff on top of it.
  406.  *   Note that the drawer is a separate object.
  407.  */
  408. room3desk: surface, fixeditem
  409.     sdesc = "small wooden desk"
  410.     noun = 'desk'
  411.     adjective = 'small' 'wooden' 'wood'
  412.     location = startroom
  413.     ldesc =
  414.     {
  415.         "It's the small desk that comes with all of the rooms in the house.
  416.     The desktop is pitifully small, especially considering that you often
  417.     need to have several physics texts and tables of integrals open
  418.     simultaneously. The desk has a small drawer (";
  419.     if ( room3drawer.isopen ) "open"; else "closed";
  420.     "). ";
  421.     }
  422.     /*
  423.      *   For convenience, redirect any open/close activity to the
  424.      *   drawer.  Since the desk can't be opened and closed, we can
  425.      *   reasonably expect that the player is really referring to the
  426.      *   drawer if he tries to open or close the desk.
  427.      */
  428.     verDoOpen( actor ) = { room3drawer.verDoOpen( actor ); }
  429.     doOpen( actor ) = { room3drawer.doOpen( actor ); }
  430.     verDoClose( actor ) = { room3drawer.verDoClose( actor ); }
  431.     doClose( actor ) = { room3drawer.doClose( actor ); }
  432. ;
  433.  
  434. /*
  435.  *   A container can contain stuff.  An openable is a special type of container
  436.  *   that can be opened and closed.  Though it's technically part of the desk,
  437.  *   it's a fixeditem (==> it can't be taken), so we can just as well make it
  438.  *   part of startroom; note that this is in fact necessary, since if it were
  439.  *   located in the desk, it would appear to be ON the desk (since the desk is
  440.  *   a surface).
  441.  */
  442. room3drawer: openable, fixeditem
  443.     isopen = nil
  444.     sdesc = "drawer"
  445.     noun = 'drawer'
  446.     location = startroom
  447. ;
  448.  
  449. /*
  450.  *   A qcontainer is a "quiet container."  It acts like a container in all
  451.  *   ways, except that its contents aren't displayed in a room's message.
  452.  *   We want the player to have to think to examine the wastebasket more
  453.  *   carefully to find out what's in it, so we'll make it a qcontainer.
  454.  *   Which is fairly natural:  when looking around a room, you don't usually
  455.  *   notice what's in a waste basket, even though you may notice the waste
  456.  *   basket itself.
  457.  *
  458.  *   The sdesc is just the name of the object, as displayed by the game
  459.  *   (as in "You see a wastebasket here").  The noun and adjective lists
  460.  *   specify how the user can refer to the object; only enough need be
  461.  *   specified by the user to uniquely identify the object for the purpose
  462.  *   of the command.  Hence, you can specify as many words as you want without
  463.  *   adding any burden to the user---the more words the better.  The location
  464.  *   specifies the object (a room in this case) where the object is
  465.  *   to be found.
  466.  */
  467. wastebasket: qcontainer
  468.     sdesc = "waste basket"
  469.     noun = 'basket' 'wastebasket'
  470.     adjective = 'waste'
  471.     location = startroom
  472.     moveInto( obj ) =
  473.     {
  474.         /*
  475.      *   If this object is ever removed from its original location,
  476.      *   turn off the "quiet" attribute.
  477.      */
  478.         self.isqcontainer := nil;
  479.     pass moveInto;
  480.     }
  481. ;
  482.  
  483. /*
  484.  *   A beditem is something you can lie down on.
  485.  */
  486. bed: beditem
  487.     noun = 'bed'
  488.     location = startroom
  489.     ldesc = "It's a perfectly ordinary bed. It's particularly ordinary
  490.      (for around here, anyway) in that it hasn't been made in a very
  491.      long time. "
  492.     
  493.     /*
  494.      *   verDoLookunder is called when the player types "look under bed"
  495.      *   to verify that this object can be used as a direct object (Do) for
  496.      *   that verb (Lookunder).  If no message is printed, it means that
  497.      *   it can be used.
  498.      */
  499.     verDoLookunder( actor ) = {}
  500.     
  501.     /*
  502.      *   ...and then, if verification succeeded, doLookunder is called to
  503.      *   actually apply the verb (Lookunder) to this direct object (do).
  504.      */
  505.     doLookunder( actor ) =
  506.     {
  507.         if ( dollar.isfound )       // already found the dollar?
  508.         "You don't find anything of interest. ";
  509.     else
  510.     {
  511.         dollar.isfound := true;
  512.         "You find a dollar bill! You pocket the bill.
  513.         (Okay, so it's an obvious adventure game puzzle, but I'm sure
  514.         you would have been disappointed if nothing had been there.) ";
  515.         dollar.moveInto( Me );
  516.     }
  517.     }
  518.     
  519.     /*
  520.      *   Verification and action for the "Make" verb.
  521.      */
  522.     verDoMake( actor ) = {}
  523.     doMake( actor ) =
  524.     {
  525.         "It was a nice thought, but you suddenly realize that you never
  526.     learned how. ";
  527.     }
  528. ;
  529.  
  530. /*
  531.  *   We wish to add the verb "make."  We need to specify the sdesc (printed
  532.  *   by the system under certain circumstances), the vocabulary word itself
  533.  *   (as it will be entered by the user), and the suffix of the method that
  534.  *   will be called in direct objects.  By specifying a doAction of 'Make',
  535.  *   we are establishing that verDoMake and doMake messages will be sent to
  536.  *   the direct object of the verb.
  537.  */
  538. makeVerb: deepverb
  539.     sdesc = "make"
  540.     verb = 'make'
  541.     doAction = 'Make'
  542. ;
  543.  
  544. /*
  545.  *   An "item" is the most basic class of objects that a user can carry
  546.  *   around.  An item has no special properties.  The "iscrawlable"
  547.  *   attribute that we're setting here is used in the north-south crawl
  548.  *   in the steam tunnels (later in the game); setting it to "true"
  549.  *   means that the player can carry this object through the crawl.
  550.  */
  551. dollar: item
  552.     sdesc = "one dollar bill"
  553.     noun = 'bill'
  554.     adjective = 'dollar' 'one' '1'
  555.     iscrawlable = true
  556. ;
  557.  
  558. room4: room
  559.     sdesc = "Room 4"
  560.     ldesc = "This is room 4, where the weird senior across the hall
  561.      lives. An exit is to the east, and a strange passage leads down. "
  562.     east = alley1
  563.     out = alley1
  564.     down =
  565.     {
  566.         /*
  567.      *   This is a bit of code attached to a direction.  We can do
  568.      *   anything we want in code like this, so long as we return a
  569.      *   room (or nil) when we're done.  In this case, we just want
  570.      *   to display a message when the player travels this way.
  571.      */
  572.         "The passage takes you down a winding stairway to a previously
  573.     unseen entrance to...\b";
  574.         return( shiproom );
  575.     }
  576. ;
  577.  
  578. /*
  579.  *   A readable is an object that can be read, such as a note, a sign, a
  580.  *   book, or a memo.  By default, reading the object displays its ldesc.
  581.  *   However, if a separate readdesc is specified, "look at note" and
  582.  *   "read note" could display different messages.
  583.  */
  584. winNote: readable
  585.     iscrawlable = true
  586.     sdesc = "note"
  587.     ldesc = "Congratulations! You've broken the stack! Please take this
  588.      fine WarpMaster 2000(tm) warp motivator, with my compliments. I'll
  589.      see you in \"Deep Space Drifter\"! "
  590.     noun = 'note'
  591.     location = room4
  592. ;
  593.  
  594. shiproom: room
  595.     sdesc = "Spaceship Room"
  596.     ldesc = "This is a very large cave dominated by a tall spaceship.
  597.      High above, a vertical tunnel leads upward; it is evidently a launch
  598.      tube for the spaceship. The exit is north. "
  599.     north = chuteroom
  600.     in = shipinterior
  601.     up =
  602.     {
  603.         "The tunnel is far too high above to climb. ";
  604.     return( nil );
  605.     }
  606. ;
  607.  
  608. /*
  609.  *   The receptacle is both a fixeditem (something that can't be taken and
  610.  *   carried around) and a container, so both superclasses are specified.
  611.  */
  612. shiprecept: fixeditem, container
  613.     sdesc = "socket"
  614.     noun = 'socket'
  615.     location = shiproom
  616.     ioPutIn( actor, dobj ) =
  617.     {
  618.         /*
  619.      *   We only want to allow the warp motivator to be put in here.
  620.      *   Check any object going in and disallow it if it's anything else.
  621.      */
  622.         if ( dobj = motivator )
  623.     {
  624.         "It fits snugly. ";
  625.         dobj.moveInto( self );
  626.     }
  627.     else "It doesn't fit. ";
  628.     }
  629. ;
  630.  
  631. spaceship: fixeditem
  632.     sdesc = "spaceship"
  633.     noun = 'spaceship' 'ship'
  634.     adjective = 'space'
  635.     location = shiproom
  636.     ldesc =
  637.     {
  638.         "The spaceship is a tall gray metal cylinder with a pointed nosecone
  639.     high above, and three large fins at the bottom. A large socket ";
  640.     if ( motivator.location = shiprecept )
  641.         "on the side contains a warp motivator. ";
  642.     else
  643.         "is on the side (the socket is currently empty). The socket
  644.         is labelled \"insert warp motivator here.\" ";
  645.     "You can enter the spaceship through an open door. ";
  646.     }
  647.     verDoEnter( actor ) = {}
  648.     doEnter( actor ) = { self.doBoard( actor ); }
  649.     verDoBoard( actor ) = {}
  650.     doBoard( actor ) =
  651.     {
  652.         actor.travelTo( shipinterior );
  653.     }
  654. ;
  655.  
  656. shipinterior: room
  657.     sdesc = "Spaceship"
  658.     out = shiproom
  659.     ldesc = "You are in the cockpit of the spaceship. The control panel is
  660.      quite simple; the only feature that interests you at the moment is
  661.      a button labelled \"Launch.\" "
  662. ;
  663.  
  664. /*
  665.  *   This is a fake "ship" that the player can refer to while inside the
  666.  *   spaceship.  This allows commands such as "look at ship" and "get out"
  667.  *   to work properly while within the ship.
  668.  */
  669. shipship: fixeditem
  670.     location = shipinterior
  671.     sdesc = "spaceship"
  672.     noun = 'ship' 'spaceship'
  673.     adjective = 'space'
  674.     ldesc = { shipinterior.ldesc; }
  675.     verDoUnboard( actor ) = {}
  676.     doUnboard( actor ) =
  677.     {
  678.         Me.travelTo( shipinterior.out );
  679.     }
  680. ;
  681.  
  682. /*
  683.  *   A buttonitem can be pushed.  It's automatically a fixeditem, and
  684.  *   always defines the noun 'button'.  The doPush method specifies what
  685.  *   happens when the button is pushed.
  686.  */
  687. launchbutton: buttonitem
  688.     sdesc = "launch button"
  689.     adjective = 'launch'
  690.     location = shipinterior
  691.     doPush( actor ) =
  692.     {
  693.         if ( motivator.location = shiprecept )
  694.     {
  695.         incscore( 10 );
  696.         "The ship's engines start to come to life. \"Launch sequence
  697.         engaged,\" the mechanical computer voice announces. ";
  698.         if ( lloyd.location = Me.location )
  699.             "\n\tLloyd heads for the door. \"Sorry,\" he says, \"I can't
  700.         go with you. Your policy specifically excludes coverage
  701.         during missions in deep space, and, frankly, it's too risky
  702.         for my tastes. Besides, I don't appear in 'Deep Space
  703.         Drifter.'\" Lloyd waves goodbye, and rolls out of the
  704.         spaceship.\n\t";
  705.         "The hatch closes automatically, sealing you into the
  706.         space vessel. The engines become louder and louder.
  707.         The computer voice announces, \"Launch
  708.         in five... four... three... two... one... liftoff!\"
  709.         The engines blast the ship into orbit.
  710.         \n\tYou realize that the time has come to set course for
  711.         \"Deep Space Drifter,\" another fine TADS adventure from
  712.         High Energy Software.\b";
  713.         
  714.         scoreRank();
  715.         terminate();
  716.         quit();
  717.         abort;
  718.     }
  719.     else
  720.     {
  721.         "The ship's computer voice announces from a hidden speaker,
  722.         \"Error: no warp motivator installed.\" ";
  723.     }
  724.     }
  725. ;
  726.  
  727. motivator: treasure
  728.     sdesc = "warp motivator"
  729.     noun = 'motivator' 'warpmaster'
  730.     takevalue = 20
  731.     adjective = 'warp'
  732.     location = room4
  733.     ldesc = "It's a WarpMaster 2000(tm), the top-of-the-line model. "
  734. ;
  735.  
  736. foodthing: fooditem
  737.     noun = 'food'
  738.     sdesc = "food"
  739.     adesc = "some food"
  740.     ldesc = "It's a non-descript food item of the type the Food Service
  741.      typically prepares. "
  742.     location = room3drawer
  743. ;
  744.  
  745. /*
  746.  *   An openable is a container, with the additional property that it can
  747.  *   be opened and closed.  To simplify things, we don't have a separate
  748.  *   cap; use of the cap is implied in the "open" and "close" commands.
  749.  */
  750. bottle: openable
  751.     sdesc = "two-liter plastic bottle"
  752.     noun = 'bottle'
  753.     location = wastebasket
  754.     adjective = 'two-liter' 'plastic' 'two' 'liter'
  755.     isopen = nil
  756.     ldesc =
  757.     {
  758.         "The bottle is ";
  759.         if ( self.isfull ) "full of liquid nitrogen. ";
  760.     else "empty. ";
  761.  
  762.     "It's "; if ( self.isopen ) "open. "; else "closed. ";
  763.     
  764.     if ( funnel.location = self )
  765.         "There's a funnel in the bottle's mouth. ";
  766.     }
  767.     ioPutIn( actor, dobj ) =
  768.     {
  769.         if ( not self.isopen )
  770.     {
  771.         "It might help to open the bottle first. ";
  772.     }
  773.         else if ( dobj = ln2 )
  774.     {
  775.         if ( funnel.location = self )
  776.         {
  777.             "You manage to get some liquid nitrogen into the bottle. ";
  778.         bottle.isfull := true;
  779.         }
  780.         else
  781.         {
  782.             "You can't manage to get any liquid nitrogen into the
  783.              tiny opening. ";
  784.             }
  785.     }
  786.     else if ( dobj = funnel )
  787.     {
  788.         "A perfect fit! ";
  789.         funnel.moveInto( self );
  790.     }
  791.     else "That won't fit in the bottle. ";
  792.     }
  793.     verIoPourIn( actor ) = {}
  794.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  795.     doClose( actor ) =
  796.     {
  797.         if ( funnel.location = self )
  798.         "You'll have to take the funnel out first. ";
  799.     else if ( self.isfull )
  800.     {
  801.         "It takes some effort to close the bottle, since the rapidly
  802.         evaporating nitrogen occupies much more volume as a gas than
  803.         as a liquid. However, you manage to close it. ";
  804.         notify( self, #explodeWarning, 3 );
  805.         self.isopen := nil;
  806.     }
  807.     else
  808.     {
  809.         "Okay, it's closed. ";
  810.         self.isopen := nil;
  811.     }
  812.     }
  813.     
  814.     /*
  815.      *   explodeWarning is sent to the bottle as a "notification," which is
  816.      *   a message that's scheduled to occur some number of turns in the
  817.      *   future.  In this case, closing the bottle while it has liquid
  818.      *   nitrogen inside will set the explodeWarning notification.
  819.      */
  820.     explodeWarning =
  821.     {
  822.         if ( not self.isopen )
  823.     {
  824.         if ( self.isIn( Me.location ))
  825.         {
  826.             "\bThe bottle is starting to make lots of noise, as though
  827.             the plastic were being stretched to its limit. ";
  828.         }
  829.         notify( self, #explode, 3 );
  830.     }
  831.     }
  832.     
  833.     /*
  834.      *   explode is set as a notification by explodeWarning.  This routine
  835.      *   actually causes the explosion.  Since the bottle explodes, we will
  836.      *   remove it from the game (by moving it into "nil").  If the bottle
  837.      *   is in the right place, we'll also do some useful things.
  838.      */
  839.     explode =
  840.     {
  841.         if ( not self.isopen )
  842.     {
  843.         "\b";
  844.         if ( self.location = banksafe )
  845.         {
  846.             if ( Me.location = bankvault )
  847.         {
  848.             "There is a terrible explosion from within the safe.
  849.              The door blasts open with a clang and a huge cloud of
  850.              water vapor. ";
  851.              
  852.             if ( lloyd.location = bankvault )
  853.                 "\n\tLloyd throws himself between you and the
  854.             vault. \"Please be careful!\" he admonishes.
  855.             \"The payment for Accidental Death due to Explosion
  856.             is enormous!\" ";
  857.         }
  858.         else
  859.             "You hear a distant, muffled explosion. ";
  860.         
  861.         banksafe.isopen := true;
  862.         banksafe.isblasted := true;
  863.         }
  864.         else if ( self.isIn( Me.location ))
  865.         {
  866.             "The bottle explodes with a deafening boom and a huge
  867.             cloud of water vapor. As with most explosions, standing
  868.         in such close proximity was not advisable; it was, in
  869.         fact, fatal. ";
  870.         die();
  871.         abort;
  872.         }
  873.         else
  874.         {
  875.             "You hear a distant explosion. ";
  876.         }
  877.         
  878.         self.moveInto( nil );
  879.     }
  880.     }
  881. ;
  882.  
  883. /*
  884.  *   We're defining our own "class" of objects here.  Up to now, we've been
  885.  *   using classes defined in "adv.t", which you will recall we included at
  886.  *   the top of the file.  This class has some useful properties.  For one,
  887.  *   it has an attribute (istreasure) that tells us that the object is
  888.  *   indeed a treasure (used in the slot in room 4's door to ensure that
  889.  *   an object can be put in the slot).  In addition, it supplements the
  890.  *   doTake routine:  when a treasure is taken for the first time, we'll
  891.  *   add the object's "takevalue" to the overall score.
  892.  */
  893. class treasure: item
  894.     istreasure = true
  895.     takevalue = 5       // default point value when object is taken
  896.     putvalue = 5        // default point value when object is put in slot
  897.     doTake( actor ) =
  898.     {
  899.         if ( not self.hasScored )       // have we scored yet?
  900.     {
  901.         incscore( self.takevalue ); // add our "takevalue" to the score
  902.         self.hasScored := true;     // note that we have scored
  903.     }
  904.     pass doTake;        // continue with the normal doTake from "item"
  905.     }
  906. ;
  907.  
  908. alley1: room
  909.     sdesc = "Alley One"
  910.     ldesc =
  911.     {
  912.         "You are in the eternal twilight of Alley One, one of the twisty
  913.     little passages (all different) making up the student house in
  914.     which you live. Your room (room 3) is to the east. To the west
  915.     is a door (";
  916.     if ( alley1door.isopen ) "open"; else "closed";
  917.     "), affixed to which is a large sign. An exit is south, and the
  918.     hallway continues north. ";
  919.     }
  920.     east = startroom
  921.     north = alley1n
  922.     west =
  923.     {
  924.         /*
  925.      *   Sometimes, we'll want to run some code when the player walks
  926.      *   in a particular direction rather than just go to a new room.
  927.      *   This is how.  Returning "nil" means that the player can't go
  928.      *   this way.
  929.      */
  930.     if ( alley1door.isopen )
  931.     {
  932.         return( room4 );
  933.     }
  934.     else
  935.     {
  936.             "The door is closed and locked. You might read the
  937.         sign on the door for more information. ";
  938.         return( nil );
  939.     }
  940.     }
  941.     south = breezeway
  942.     out = breezeway
  943. ;
  944.  
  945. alley1n: room
  946.     sdesc = "Alley One"
  947.     ldesc = "You are at the north end of alley 1.  A small room is
  948.      to the west. "
  949.     south = alley1
  950.     west = alley1comp
  951. ;
  952.  
  953. alley1comp: room
  954.     sdesc = "Computer Room"
  955.     ldesc = 
  956.     {
  957.         "You are in a small computer room. Not surprisingly, the room
  958.          contains a personal computer. The exit is east. ";
  959.     if ( not self.isseen ) notify( compstudents, #converse, 0 );
  960.     }
  961.     east = alley1n
  962. ;
  963.  
  964. alley1pc: fixeditem
  965.     sdesc = "personal computer"
  966.     noun = 'computer'
  967.     adjective = 'personal'
  968.     location = alley1comp
  969.     ldesc = "The computer is in use by a couple of your fellow undergraduates.
  970.      Closer inspection of the screen shows that they seem to be playing a
  971.      text adventure. You've never really understood the appeal of those games
  972.      yourself, but you quickly surmise that the game is part of one of the
  973.      seniors' stacks. "
  974.     verIoTypeOn( actor ) = {}
  975.     ioTypeOn( actor, dobj ) =
  976.     {
  977.         "The computer is already in use. Common courtesy demands that you
  978.     wait your turn. ";
  979.     }
  980.     verDoTurnoff( actor ) = {}
  981.     doTurnoff( actor ) =
  982.     {
  983.         "The students won't let you, since they're busy using the computer. ";
  984.     }
  985. ;
  986.  
  987. compstudents: Actor
  988.     location = alley1comp
  989.     sdesc = "students"
  990.     adesc = "a couple of students"
  991.     ldesc = "The students are busy using the computer. "
  992.     actorAction( v, d, p, i ) =
  993.     {
  994.         "They're too wrapped up in what they're doing. ";
  995.     exit;
  996.     }
  997.     doAskAbout( actor, io ) =
  998.     {
  999.         "They're too busy to answer. ";
  1000.     }
  1001.     noun = 'students' 'undergraduates'
  1002.     actorDesc = "A couple of your fellow undergraduates are here, using
  1003.      the computer. They seem quite absorbed in what they're doing. "
  1004.     state = 0
  1005.     converse =
  1006.     {
  1007.         if ( Me.location = self.location )
  1008.     {
  1009.         "\b";
  1010.         if ( self.state = 0 )
  1011.             "\"Where are we going to find the dollar bill?\" one
  1012.         of the students asks the other. They sit back and stare
  1013.         at the screen, lost in thought. ";
  1014.         else if ( self.state = 1 )
  1015.             "\"Hey!\" says one of the students. \"Did you look under
  1016.         the bed?\" The other student shakes his head. \"No way,
  1017.         that would be a stupid puzzle!\" ";
  1018.         else if ( self.state = 2 )
  1019.             "One of the students using the computer types a long
  1020.         string of commands, and finally types \"look under bed.\"
  1021.         \"Wow! The dollar bill actually was under the bed! How
  1022.         lame!\" ";
  1023.         else
  1024.             "The students continue to play with the computer. ";
  1025.     
  1026.         self.state := self.state + 1;
  1027.     }
  1028.     }
  1029. ;
  1030.  
  1031. class lockedDoor: fixeditem, keyedLockable
  1032.     isopen = nil
  1033.     islocked = true
  1034.     noun = 'door'
  1035.     sdesc = "door"
  1036.     ldesc =
  1037.     {
  1038.         if ( self.isopen ) "It's open. ";
  1039.     else if ( self.islocked ) "It's closed and locked. ";
  1040.     else "It's closed. ";
  1041.     }
  1042.     verIoPutIn( actor ) = { "You can't put anything in that! "; }
  1043. ;
  1044.  
  1045. alley1door: lockedDoor
  1046.     location = alley1
  1047.     ldesc =
  1048.     {
  1049.         if ( self.isopen ) "It's open. ";
  1050.     else
  1051.             "The door is closed and locked. There is a slot in the door,
  1052.             and above that, a large sign is affixed to the door. ";
  1053.     }
  1054. ;
  1055.  
  1056. alley1sign: fixeditem, readable
  1057.     noun = 'sign'
  1058.     sdesc = "sign"
  1059.     location = alley1
  1060.     ldesc = "The sign says:
  1061.      \b\t\tWelcome to Ditch Day!
  1062.      \bThis stack is a treasure hunt. Gather all of the treasures, and you
  1063.      break the stack.
  1064.      To satisfy the requirements of this stack, you must find the
  1065.      items listed below, and deposit them in the slot in the door. When
  1066.      all items have been put in the slot, the stack will be solved and
  1067.      the door will open automatically. The items to find are:
  1068.      \b\tThe Great Seal of the Omega
  1069.      \n\tMr.\ Happy Gear
  1070.      \n\tA Million Random Digits
  1071.      \n\tA DarbCard
  1072.      \bThese items are hidden amongst the expanses of the Great
  1073.      Undergraduate Excavation project. Happy hunting!
  1074.      \bFor first-time participants, please note that
  1075.      this is a \"finesse stack.\" You are not permitted to attempt to break
  1076.      the stack by brute force. Instead, you must follow the rules above. "
  1077. ;
  1078.  
  1079. alley1slot: fixeditem, container
  1080.     noun = 'slot'
  1081.     sdesc = "slot"
  1082.     location = alley1
  1083.     itemcount = 0
  1084.     ioPutIn( actor, dobj ) =
  1085.     {
  1086.         if ( dobj.istreasure )
  1087.     {
  1088.         "\^<< dobj.thedesc >> disappears into the slot. ";
  1089.         dobj.moveInto( nil );
  1090.         incscore( dobj.putvalue );
  1091.         self.itemcount := self.itemcount + 1;
  1092.         if ( self.itemcount = 4 )
  1093.         {
  1094.             "As the treasure disappears into the slot, you hear a
  1095.         klaxon from the other side of the door. An elaborate
  1096.         series of clicks and clanks follows, then the door swings
  1097.         open. ";
  1098.         alley1door.islocked := nil;
  1099.         alley1door.isopen := true;
  1100.         }
  1101.     }
  1102.     else
  1103.     {
  1104.         "The slot will only accept items on the treasure list. ";
  1105.     }
  1106.     }
  1107. ;
  1108.  
  1109. breezeway: room
  1110.     sdesc = "Breezeway"
  1111.     ldesc = "You are in a short passage that connects a courtyard,
  1112.      to the east, to the outside of the building, which lies to the
  1113.      west. A hallway leads north. "
  1114.     north = alley1
  1115.     east = courtyard
  1116.     west = orangeWalk1
  1117. ;
  1118.  
  1119. courtyard: room
  1120.     sdesc = "Courtyard"
  1121.     ldesc = "You are in a large outdoor courtyard.
  1122.      An arched passage is to the west.
  1123.      A passage leads east, and a stairway leads down. "
  1124.     east = lounge
  1125.     down = hall1
  1126.     west = breezeway
  1127. ;
  1128.  
  1129. lounge: room
  1130.     sdesc = "Lounge"
  1131.     ldesc = "You are in the lounge. A passage leads west, and a dining
  1132.      room lies to the north. "
  1133.     north = diningRoom
  1134.     west = courtyard
  1135.     out = courtyard
  1136. ;
  1137.  
  1138. diningRoom: room
  1139.     sdesc = "Dining Room"
  1140.     ldesc = "You are in the dining room. There is a wooden table in
  1141.      the center of the room. The lounge lies to the south,
  1142.      and a passage to the east leads into the kitchen. "
  1143.     east = kitchen
  1144.     south = lounge
  1145. ;
  1146.  
  1147. diningTable: surface, fixeditem
  1148.     sdesc = "wooden table"
  1149.     noun = 'table'
  1150.     adjective = 'wooden'
  1151.     location = diningRoom
  1152. ;
  1153.  
  1154. fishfood: fooditem
  1155.     noun = 'module'
  1156.     adjective = 'fish' 'protein'
  1157.     sdesc = "fish protein module"
  1158.     ldesc = "It's a small pyramid-shaped white object, which is widely
  1159.      considered to consist primarily of fish protein. The food service
  1160.      typically resorts to such unappetizing fare toward the end of the
  1161.      year. "
  1162.     location = diningTable
  1163. ;
  1164.  
  1165. kitchen: room
  1166.     sdesc = "Kitchen"
  1167.     ldesc = "You are in the kitchen.  A ToxiCola(tm) machine is here.
  1168.      A passage leads into the dining room to the west. "
  1169.     west = diningRoom
  1170.     out = diningRoom
  1171. ;
  1172.  
  1173. toxicolaMachine: fixeditem, container
  1174.     noun = 'machine' 'compartment'
  1175.     adjective = 'toxicola'
  1176.     sdesc = "ToxiCola machine"
  1177.     ldesc =
  1178.     {
  1179.         "The machine dispenses ToxiCola, one of the big losers in the
  1180.          Cola Wars.  But, hey, it's cheap, so the food service installed it.
  1181.          The machine consists of a compartment large enough for a cup,
  1182.          and a button for dispensing ToxiCola into the cup. ";
  1183.      if ( cup.location = self )
  1184.         "The compartment contains a cup. ";
  1185.     }
  1186.     location = kitchen
  1187.     ioPutIn( actor, dobj ) =
  1188.     {
  1189.         if ( dobj <> cup )
  1190.         "That won't fit in the compartment. ";
  1191.     else pass ioPutIn;
  1192.     }
  1193. ;
  1194.  
  1195. cup: container
  1196.     sdesc = "coffee cup"
  1197.     noun = 'cup'
  1198.     adjective = 'coffee'
  1199.     isFull = nil
  1200.     ldesc =
  1201.     {
  1202.         if ( self.isFull ) "It's full of a viscous brown fluid. ";
  1203.     else "It's empty. ";
  1204.     }
  1205.     location = diningTable
  1206.     ioPutIn( actor, dobj ) =
  1207.     {
  1208.         if ( dobj = ln2 ) "The liquid nitrogen evaporates on contact. ";
  1209.     else "It won't fit in the cup. ";
  1210.     }
  1211. ;
  1212.  
  1213. toxicola: fixeditem
  1214.     sdesc = "toxicola"
  1215.     noun = 'toxicola' 'cola'
  1216.     ldesc = "It's a thick brown fluid. It appears to be quite flat. "
  1217.     doTake( actor ) =
  1218.     {
  1219.         "You'll have to leave it in the cup. ";
  1220.     }
  1221.     verDoDrink( actor ) = {}
  1222.     doDrink( actor ) =
  1223.     {
  1224.         "You drink the ToxiCola, despite your better judgment. It
  1225.     initially sparks a sugar and caffeine rush, but that rapidly
  1226.     fades, to be replaced by a strange dull throbbing. You enter
  1227.     a semi-conscious state for several hours. It finally passes,
  1228.     but you're not sure if it's been hours, weeks, or years. ";
  1229.     cup.isFull := nil;
  1230.     self.moveInto( nil );
  1231.     }
  1232. ;
  1233.  
  1234. toxicolaButton: buttonitem
  1235.     location = kitchen
  1236.     sdesc = "button"
  1237.     doPush( actor ) =
  1238.     {
  1239.         if ( cup.location = toxicolaMachine )
  1240.     {
  1241.         if ( cup.isFull )
  1242.             "ToxiCola spills over the already full cup, and drains
  1243.         away. ";
  1244.         else
  1245.         {
  1246.             "The horrible brown viscous fluid you have come to
  1247.         know as ToxiCola fills the cup. ";
  1248.         cup.isFull := true;
  1249.         toxicola.moveInto( cup );
  1250.         }
  1251.     }
  1252.     else
  1253.     {
  1254.         "Horrible viscous brown fluid spills into the empty
  1255.         compartment, and drains away. ";
  1256.     }
  1257.     }
  1258. ;
  1259.  
  1260. orangeWalk1: room
  1261.     sdesc = "Orange Walk"
  1262.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1263.      continues to the north, and an arched passage leads into a building
  1264.      to the east. "
  1265.     east = breezeway
  1266.     north = orangeWalk2
  1267. ;
  1268.  
  1269. /*
  1270.  *   We want a "class" of objects for the orange trees lining the
  1271.  *   orange walk.  They don't do anything, so they're "decoration."
  1272.  */
  1273. class orangeTree: decoration
  1274.     sdesc = "orange trees"
  1275.     ldesc = "The orange trees are perfectly ordinary. "
  1276.     adesc = "an orange tree"
  1277.     noun = 'tree' 'trees'
  1278.     adjective = 'orange'
  1279.     verDoClimb( actor ) = {}
  1280.     doClimb( actor ) =
  1281.     {
  1282.         "You climb into one of the orange trees, and quickly find the
  1283.     view from the few feet higher to be highly uninteresting. You
  1284.     soon climb back down. ";
  1285.     }
  1286. ;
  1287.  
  1288. orangeTree1: orangeTree
  1289.     location = orangeWalk1
  1290. ;
  1291.  
  1292. orangeWalk2: room
  1293.     sdesc = "Orange Walk"
  1294.     ldesc = "You are on a walkway lined with orange trees. The walkway
  1295.      continues to the south, and leads into a large grassy square to the
  1296.      north. "
  1297.     north = quad
  1298.     south = orangeWalk1
  1299. ;
  1300.  
  1301. orangeTree2: orangeTree
  1302.     location = orangeWalk2
  1303. ;
  1304.  
  1305. quad: room
  1306.     sdesc = "Quad"
  1307.     ldesc = "You are on the quad, a large grassy square in the
  1308.      center of campus.  The bookstore lies to the northwest; the
  1309.      health center lies to the northeast; Buildings and Grounds
  1310.      lies to the north; and walkways lead west and south.
  1311.      \n\tSome students dressed in radiation suits are staging a bogus
  1312.      toxic leak, undoubtedly to fulfill the requirements of one of the
  1313.      stacks.  They are wandering around, looking very busy.  Many reporters
  1314.      are standing at a safe distance, looking terrified.
  1315.      The supposed clean-up crew is pouring lots of liquid nitrogen onto
  1316.      the ground, resulting in huge clouds of water vapor. "
  1317.     south = orangeWalk2
  1318.     nw = bookstore
  1319.     west = walkway
  1320.     ne = healthCenter
  1321.     north = BandG
  1322. ;
  1323.  
  1324. BandG: room
  1325.     sdesc = "B&G"
  1326.     ldesc = "You are in the Buildings and Grounds office. The exit is to
  1327.      the south. "
  1328.     south = quad
  1329.     out = quad
  1330. ;
  1331.  
  1332. bngmemo: readable
  1333.     sdesc = "scrap of paper"
  1334.     iscrawlable = true
  1335.     noun = 'scrap' 'paper'
  1336.     location = BandG
  1337.     ldesc = "Most of the paper has been torn away; the part that remains
  1338.      seems to have a list of numerical codes of some kind on it:
  1339.      \b\t293 -- north tunnel lighting
  1340.      \n\t322 -- station 2 lighting
  1341.      \n\t612 -- behavior lab
  1342.      \bThe rest is missing. "
  1343. ;
  1344.  
  1345. healthCenter: room
  1346.     sdesc = "Health Center"
  1347.     ldesc = "You are in the health center. Like the rest of campus, this
  1348.      place is deserted because of Ditch Day. The large desk would normally
  1349.      have a receptionist behind it, but today, no one is in sight. "
  1350.     sw = quad
  1351.     out = quad
  1352. ;
  1353.  
  1354. healthDesk: fixeditem, surface
  1355.     sdesc = "desk"
  1356.     noun = 'desk'
  1357.     adjective = 'large'
  1358.     location = healthCenter
  1359. ;
  1360.  
  1361. healthMemo: readable
  1362.     sdesc = "health memo"
  1363.     iscrawlable = true
  1364.     noun = 'memo'
  1365.     plural = 'memos'
  1366.     adjective = 'health'
  1367.     location = healthDesk
  1368.     ldesc =
  1369.        "From:\t\tDirector of the Health Center
  1370.       \nTo:\t\tAll Health Center Personnel
  1371.       \nSubject:\tToxiCola toxicity
  1372.       \bMany students have visited the Health Center recently, complaining
  1373.       that the ToxiCola that is served in the student houses has not been
  1374.       properly caffeinated.  The students are complaining of drowsiness,
  1375.       dizziness, and other symptoms that are normally associated with an
  1376.       insufficient intake of caffeine.
  1377.       \n\tUpon investigation, we have learned that the ToxiCola dispensers
  1378.       in the student houses have become contaminated with a substance that
  1379.       induces these effects. The substance has not yet been identified, but
  1380.       the concentration seems to be increasing. All Health Center personnel
  1381.       are urgently directed to advise students to avoid the ToxiCola if at
  1382.       all possible. Students should be informed that their student health
  1383.       insurance coverage will cover any purchases of other caffeinated
  1384.       beverages that they need for their studies. "
  1385. ;
  1386.  
  1387. students: decoration
  1388.     sdesc = "students"
  1389.     adesc = "a group of students"
  1390.     noun = 'student' 'students'
  1391.     location = quad
  1392.     ldesc = "The students are making quite a good show of the simulated
  1393.      nuclear waste spill. They're all wearing white clean-room suits with
  1394.      official-looking \"Radiation Control District\" badges. They're
  1395.      scampering about purposefully, keeping the crowd of reporters back
  1396.      at a safe distance. "
  1397. ;
  1398.  
  1399. presscorp: decoration
  1400.     sdesc = "reporters"
  1401.     adesc = "a group of reporters"
  1402.     noun = 'reporter' 'reporters'
  1403.     location = quad
  1404. ;
  1405.  
  1406. flask: container
  1407.     sdesc = "flask"
  1408.     ldesc = "The flask appears to have lots of liquid nitrogen in it;
  1409.      it's hard to tell just how much, since the opening is perpetually
  1410.      clouded over with thick plumes of water vapor. "
  1411.     noun = 'flask'
  1412.     location = quad
  1413.     ioPutIn( actor, dobj ) =
  1414.     {
  1415.         "You know from experience that it wouldn't be a good idea to
  1416.     put "; dobj.thedesc; " into the liquid nitrogen, since the LN2 is
  1417.     really, really cold. ";
  1418.     }
  1419. ;
  1420.  
  1421. pourVerb: deepverb
  1422.     sdesc = "pour"
  1423.     verb = 'pour'
  1424.     doAction = 'Pour'
  1425.     ioAction( inPrep ) = 'PourIn'
  1426.     ioAction( onPrep ) = 'PourOn'
  1427. ;
  1428.  
  1429. ln2: item
  1430.     sdesc = "liquid nitrogen"
  1431.     adesc = "some liquid nitrogen"      // "a liquid nitrogen" doesn't compute
  1432.     ldesc = "You can't see much, thanks to the thick clouds of water
  1433.      vapor that inevitably form over such a cold substance. "
  1434.     noun = 'nitrogen' 'ln2'
  1435.     adjective = 'liquid'
  1436.     location = flask
  1437.     doTake( actor ) =
  1438.     {
  1439.         "You're better off leaving the liquid nitrogen in the flask. ";
  1440.     }
  1441.     verDoPour( actor ) = {}
  1442.     verDoPourIn( actor, io ) = {}
  1443.     doPour( actor ) =
  1444.     {
  1445.         askio( inPrep );
  1446.     }
  1447. ;
  1448.  
  1449. walkway: room
  1450.     sdesc = "Walkway"
  1451.     ldesc = "You are on a walkway.  A large grassy square lies to the east;
  1452.      buildings lie to the north and south. The walkway continues west. "
  1453.     east = quad
  1454.     north = behaviorLab
  1455.     south = security
  1456.     west = walkway2
  1457. ;
  1458.  
  1459. walkway2: room
  1460.     sdesc = "Walkway"
  1461.     ldesc = "You are on a walkway, which continues to the east. Buildings
  1462.      are to the north and south. "
  1463.     east = walkway
  1464.     south = explosiveLab
  1465.     north = biobuilding
  1466. ;
  1467.  
  1468. biobuilding: room
  1469.     sdesc = "Biology Building"
  1470.     ldesc = "You are in the biology building. The exit is south. "
  1471.     south = walkway2
  1472.     out = walkway2
  1473. ;
  1474.  
  1475. bionotes: readable
  1476.     sdesc = "notebook"
  1477.     location = biobuilding
  1478.     noun = 'notebook'
  1479.     ldesc = "The notebook explains various lab techniques used in cloning
  1480.      organisms. Since the invention of the CloneMaster, which requires only
  1481.      a sample of genetic material from a subject (such as some blood, or a
  1482.      bit of skin, or the like) and the basic skills required to operate a
  1483.      household blender, most of the techniques are obsolete. Some of the data,
  1484.      however, are interesting. For example, the notebook outlines the procedure
  1485.      for reversing the sex of a clone; the introduction of chemicals identified
  1486.      herein only as Genetic Factor XQ3, Polymerase Blue, and Compound T99 at
  1487.      the start of the cloning process aparently does the trick. Most of the
  1488.      rest of the document is a discussion of the human immune system; the
  1489.      author comes to the conclusion that the human immune system, though a
  1490.      novel idea, is far too improbable to ever actually be implemented. "
  1491. ;
  1492.  
  1493. explosiveLab: room
  1494.     sdesc = "Explosive Lab"
  1495.     ldesc = "It's not that the lab itself is explosive (though it has blown
  1496.      up a couple times in the past); rather, they study explosives here.
  1497.      Unfortunately, all the good stuff has been removed by other Ditch Day
  1498.      participants who got up earlier than you did. The exit is north. "
  1499.     north = walkway2
  1500.     out = walkway2
  1501. ;
  1502.  
  1503. ln2doc: readable
  1504.     sdesc = "thesis"
  1505.     noun = 'thesis'
  1506.     location = explosiveLab
  1507.     ldesc = "The thesis is about Thermal Expansion Devices. It explains about
  1508.      a new class of explosives that are made possible by low-temperature
  1509.      fluid technology (i.e., liquid nitrogen) and high-tension polymer
  1510.      containment vessels (i.e., plastic bottles). A great deal of jargon and
  1511.      complicated theories are presented, presumably to fool the faculty
  1512.      advisor into thinking the author actually did something useful with his
  1513.      research funds; after wading through the nonsense, you find that the
  1514.      paper is merely talking about putting liquid nitrogen into a plastic
  1515.      soft-drink bottle, closing the bottle, then letting nature take its
  1516.      course. Since the nitrogen will tend to evaporate at room temperature,
  1517.      but will have no place to go, the bottle will eventually explode.
  1518.      \bOn the cover page, you notice this important warning: \"Kids! Don't
  1519.      try this at home! Liquid nitrogen is extremely cold, and can cause severe
  1520.      injuries; it should only be handled by trained professionals. Never
  1521.      put liquid nitrogen in a closed container.\" "
  1522. ;
  1523.  
  1524. bookstore: room
  1525.     sdesc = "Bookstore"
  1526.     ldesc = "You are in the bookstore. The shelves are quite empty; no doubt
  1527.      everything has been bought up by seniors in attempts to build their
  1528.      stacks and underclassmen in attempts to break them. The exit is to the
  1529.      southeast. "
  1530.     out = { return( self.se ); }
  1531.     se =
  1532.     {
  1533.         /*
  1534.      *   We need to check that the battery has been paid for, if it's
  1535.      *   been taken.  If not, don't let 'em out.
  1536.      */
  1537.         if ( battery.isIn( Me ) and not battery.isPaid )
  1538.     {
  1539.         "The clerk notices that you want to buy the battery. \"That'll be
  1540.         five dollars,\" she says, waiting patiently. ";
  1541.         return( nil );
  1542.     }
  1543.     else return( quad );
  1544.     }
  1545. ;
  1546.  
  1547. battery: item
  1548.     location = bookstore
  1549.     isPaid = nil
  1550.     sdesc = "battery"
  1551.     noun = 'battery'
  1552.     verDoPayfor( actor ) =
  1553.     {
  1554.         if ( actor.location <> bookstore )
  1555.         "I don't see anyone to pay! ";
  1556.     }
  1557.     doPayfor( actor ) =
  1558.     {
  1559.         clerk.doPay( actor );
  1560.     }
  1561.     verIoPayFor( actor ) = {}
  1562.     ioPayFor( actor, dobj ) =
  1563.     {
  1564.         if ( dobj <> clerk )
  1565.     {
  1566.         "You can't pay "; dobj.thedesc; " for that! ";
  1567.     }
  1568.     else clerk.doPay( actor );
  1569.     }
  1570. ;
  1571.  
  1572. forPrep: Prep
  1573.     sdesc = "for"
  1574.     preposition = 'for'
  1575. ;
  1576.  
  1577. payVerb: deepverb
  1578.     sdesc = "pay"
  1579.     verb = 'pay'
  1580.     doAction = 'Pay'
  1581.     ioAction( forPrep ) = 'PayFor'
  1582. ;
  1583.  
  1584. payforVerb: deepverb
  1585.     verb = 'pay for'
  1586.     sdesc = "pay for"
  1587.     doAction = 'Payfor'
  1588. ;
  1589.  
  1590. money: item
  1591.     sdesc = "five dollar bill"
  1592.     noun = 'bill' 'money'
  1593.     adjective = 'five' 'dollar' '5'
  1594.     iscrawlable = true
  1595. ;
  1596.  
  1597. clerk: Actor
  1598.     noun = 'clerk'
  1599.     location = bookstore
  1600.     sdesc = "Clerk"
  1601.     ldesc = "The clerk is a kindly lady to whom you have paid many hundreds
  1602.      of dollars for books and other college necessities. "
  1603.     actorDesc = "A clerk is near the exit, prepared to ring up any purchases
  1604.      you might want to make (not that there's much left here to buy). "
  1605.     verIoGiveTo( actor ) = {}
  1606.     ioGiveTo( actor, dobj ) =
  1607.     {
  1608.         if ( dobj = money or dobj = dollar ) self.doPay( actor );
  1609.     else if ( dobj = darbcard )
  1610.     {
  1611.         "The clerk shakes her head. \"Sorry,\" she says, \"we only
  1612.         accept cash.\" ";
  1613.     }
  1614.     else if ( dobj = cup and cup.isFull )
  1615.     {
  1616.         "\"I never drink that stuff,\" the clerk says, \"and neither
  1617.         should you! Do you have any idea what's in there? I probably
  1618.         don't know half as much chemistry as you, but I know better
  1619.         than to drink that.\" ";
  1620.     }
  1621.     else
  1622.     {
  1623.         "She doesn't appear interested. ";
  1624.     }
  1625.     }
  1626.     verDoPay( actor ) = {}
  1627.     doPay( actor ) =
  1628.     {
  1629.         if ( not battery.isIn( Me ))
  1630.     {
  1631.         "The clerk looks confused. \"I don't see what you're
  1632.         paying for,\" she says. She then looks amused, realizing
  1633.         that the students here somtimes get a little ahead of
  1634.         themselves. ";
  1635.     }
  1636.     else if ( battery.isPaid )
  1637.     {
  1638.         "The clerk looks confused and says, \"You've already paid!\"
  1639.         She then looks amused, realizing that the students here can
  1640.         be a bit absent-minded at times. ";
  1641.     }
  1642.         else if ( not money.isIn( Me ))
  1643.     {
  1644.         if ( dollar.isIn( Me ))
  1645.         {
  1646.             "The clerk reminds you that the battery is five dollars.
  1647.         All you have is one dollar. She looks amused; \"They can
  1648.         do calculus in their sleep but they can't add,\" she jokes. ";
  1649.         }
  1650.         else
  1651.         {
  1652.             "You unfortunately don't have anything with which to pay the
  1653.             clerk. ";
  1654.         }
  1655.     }
  1656.     else
  1657.     {
  1658.         "The clerk accepts your money and says \"Thank you, have a nice
  1659.         day.\"";
  1660.         battery.isPaid := true;
  1661.         money.moveInto( nil );
  1662.     }
  1663.     }
  1664. ;
  1665.  
  1666. behaviorLab: room
  1667.     sdesc = "Behavior Lab"
  1668.     ldesc = "You are in the behavior lab.  The exit is to the south,
  1669.      and a locked door is to the north. The door is labelled \"Maze -
  1670.      Experimental Subjects Only.\" In addition, a passage labelled
  1671.      \"Viewing Room\" leads east. "
  1672.     south = walkway
  1673.     out = walkway
  1674.     east = mazeview
  1675.     north =
  1676.     {
  1677.         "The door is closed and locked. Besides, do you really want to
  1678.     be an \"Experimental Subject\"?";
  1679.     return( nil );
  1680.     }
  1681. ;
  1682.  
  1683. mazeview: room
  1684.     sdesc = "Maze Viewing Room"
  1685.     ldesc =
  1686.     {
  1687.         "The entire north wall of this room is occupied by a window
  1688.          overlooking a vast human-sized labyrinth. No experimental subjects
  1689.          (i.e., students) seem to be wandering through the maze at the
  1690.      moment, ";
  1691.      
  1692.     if ( not mazeStart.isseen )
  1693.         "but you have the strange feeling that you will have to find
  1694.         your way through the maze some day. You read with a sense of
  1695.         foreboding the plaque affixed to the wall:\b";
  1696.     else
  1697.             "so your attention wanders to the plaque on the wall:\b";
  1698.         
  1699.         mazeplaque.ldesc;
  1700.     }
  1701.     west = behaviorLab
  1702. ;
  1703.  
  1704. mazewindow: fixeditem
  1705.     sdesc = "window"
  1706.     noun = 'window'
  1707.     location = mazeview
  1708.     verDoLookthru( actor ) = {}
  1709.     doLookthru( actor ) = { self.ldesc; }
  1710.     ldesc =
  1711.     {
  1712.         "The window looks out onto a vast human-sized labyrinth.
  1713.          The maze is currently devoid of experimental subjects";
  1714.     if ( not mazeStart.isseen )
  1715.         ", but you have the strange feeling that you'll have to find
  1716.         your way through the maze someday";
  1717.     ". ";
  1718.     }
  1719. ;
  1720.  
  1721. mazeplaque: fixeditem, readable
  1722.     sdesc = "plaque"
  1723.     noun = 'plaque'
  1724.     location = mazeview
  1725.     ldesc = "*** The Behavioral Biology Laboratory Psycho-Magnetic Maze ***
  1726.      \bThe Psycho-Magnetic Maze that is visible through the window has been
  1727.      constructed to determine how the human directional sense interacts with
  1728.      strong electromagnetic and nuclear fields. Through careful tuning of
  1729.      these fields, we have found that human subjects often become completely
  1730.      disoriented in the maze, resulting in hours of random and
  1731.      desperate wandering, and much amusement to those of us in the observation
  1732.      room. "
  1733. ;
  1734.  
  1735. behaviorDoor: lockedDoor
  1736.     ldesc = "The door is closed and locked, and labelled \"Experimental
  1737.      Subjects Only.\""
  1738.     location = behaviorLab
  1739. ;
  1740.  
  1741. security: room
  1742.     sdesc = "Security Office"
  1743.     ldesc = "You are in the campus security office, the very nerve-center of
  1744.      the elite Kaltech Kops.  The officers all
  1745.      appear to be absent; undoubtedly they are all scurrying hither and
  1746.      yon trying to deal with the ditch-day festivities.  There is a desk
  1747.      in the center of the room.  The exit is to
  1748.      the north. "
  1749.     north = walkway
  1750.     out = walkway
  1751. ;
  1752.  
  1753. securityDesk: fixeditem, surface
  1754.     sdesc = "desk"
  1755.     noun = 'desk'
  1756.     location = security
  1757. ;
  1758.  
  1759. securityMemo: readable
  1760.     sdesc = "security memo"
  1761.     iscrawlable = true
  1762.     noun = 'memo'
  1763.     plural = 'memos'
  1764.     adjective = 'security'
  1765.     location = securityDesk
  1766.     ldesc =
  1767.        "From:\t\tDirector of Security
  1768.       \nTo:\t\tAll Security Personnel
  1769.       \nSubject:\tGreat Undergraduate Excavation
  1770.       \bIt has come to the attention of the Kaltech Kops that the student
  1771.       activity in the steam tunnels, known as the \"Great Undergraduate
  1772.       Excavation\" project, has escalated vastly in recent years. Due to
  1773.       objections from city officials about noise from underground and the
  1774.       fear local residents have expressed that their property will be
  1775.       undermined, this office has taken action to halt all GUE activity.
  1776.       Effective immediately, a security officer will be posted at all
  1777.       known steam tunnel entrances, and shall under no circumstances allow
  1778.       students to enter. "
  1779. ;
  1780.  
  1781. flashlight: container, lightsource
  1782.     sdesc = "flashlight"
  1783.     noun = 'flashlight' 'light'
  1784.     adjective = 'flash'
  1785.     location = security
  1786.     ioPutIn( actor, dobj ) =
  1787.     {
  1788.         if ( dobj <> battery )
  1789.     {
  1790.         "You can't put "; dobj.thedesc; " into the flashlight. ";
  1791.     }
  1792.     else pass ioPutIn;
  1793.     }
  1794.     Grab( obj ) =
  1795.     {
  1796.         /*
  1797.      *   Grab( obj ) is invoked whenever an object 'obj' that was
  1798.      *   previously located within me is removed.  If the battery is
  1799.      *   removed, the flashlight turns off.
  1800.      */
  1801.         if ( obj = battery ) self.islit := nil;
  1802.     }
  1803.     ldesc =
  1804.     {
  1805.         if ( battery.location = self )
  1806.     {
  1807.         if ( self.islit )
  1808.             "The flashlight (which contains a battery) is turned on
  1809.         and is providing a warm, reassuring beam of light. ";
  1810.         else
  1811.             "The flashlight (which contains a battery) is currently off. ";
  1812.     }
  1813.     else
  1814.     {
  1815.         "The flashlight is off. It seems to be missing a battery. ";
  1816.     }
  1817.     }
  1818.     verDoTurnon( actor ) =
  1819.     {
  1820.         if ( self.islit ) "It's already on! ";
  1821.     }
  1822.     doTurnon( actor ) =
  1823.     {
  1824.         if ( battery.location = self )
  1825.     {
  1826.         "The flashlight is now on. ";
  1827.         self.islit := true;
  1828.     }
  1829.     else "The flashlight won't turn on without a battery. ";
  1830.     }
  1831.     verDoTurnoff( actor ) =
  1832.     {
  1833.         if ( not self.islit ) "It's not on. ";
  1834.     }
  1835.     doTurnoff( actor ) =
  1836.     {
  1837.         "Okay, the flashlight is now turned off. ";
  1838.     self.islit := nil;
  1839.     }
  1840. ;
  1841.  
  1842. goToSleep: function
  1843. {
  1844. }
  1845.  
  1846. hall1: room
  1847.     sdesc = "Hallway"
  1848.     ldesc = "You are at the west end of a basement hallway. A stairway
  1849.      leads up. "
  1850.     up = courtyard
  1851.     east = hall2
  1852. ;
  1853.  
  1854. hall2: room
  1855.     sdesc = "Hallway"
  1856.     ldesc = "You are in an east-west hallway in the basement.  Another hallway
  1857.      goes off to the north. "
  1858.     west = hall1
  1859.     east = hall3
  1860.     north = hall4
  1861. ;
  1862.  
  1863. hall3: room
  1864.     sdesc = "Hallway"
  1865.     ldesc = "You are at the east end of a hallway in the basement.
  1866.      A passage leads north. "
  1867.     west = hall2
  1868.     north = laundry
  1869. ;
  1870.  
  1871. laundry: room
  1872.     sdesc = "Laundry Room"
  1873.     ldesc = "You are in the laundry room. There is a washing machine
  1874.      against one wall. The exit is to the south. "
  1875.     south = hall3
  1876.     out = hall3
  1877. ;
  1878.  
  1879. washingMachine: fixeditem, openable
  1880.     sdesc = "washing machine"
  1881.     isopen = nil
  1882.     location = laundry
  1883.     noun = 'machine' 'washer'
  1884.     adjective = 'washing'
  1885. ;
  1886.  
  1887. jeans: item
  1888.     sdesc = "blue jeans"
  1889.     location = washingMachine
  1890.     noun = 'jeans' 'pants'
  1891.     adjective = 'blue'
  1892.     ldesc =
  1893.     {
  1894.         if ( self.isseen ) "It's an ordinary pair of jeans. ";
  1895.     else
  1896.     {
  1897.         "It looks like an ordinary pair of jeans, though not
  1898.         your size. As you inspect them, you notice a key fall
  1899.         out of them and to the ground. ";
  1900.         masterKey.moveInto( Me.location );
  1901.         self.isseen := true;
  1902.     }
  1903.     }
  1904.     verDoLookin( actor ) = {}
  1905.     doLookin( actor ) = { self.ldesc; }
  1906.     verDoWear( actor ) = { "They're not your size. "; }
  1907. ;
  1908.  
  1909. masterKey: keyItem
  1910.     iscrawlable = true
  1911.     sdesc = "master key"
  1912.     noun = 'key'
  1913.     adjective = 'master'
  1914.     doTake( actor ) =
  1915.     {
  1916.         if ( not self.isseen )
  1917.     {
  1918.         "*Some* adventure games would try to impose their authors'
  1919.         misguided sense of ethics on you at this point, telling you
  1920.         that you don't feel like picking up the key, or you don't have
  1921.         time to do that, or that it's against the rules to even possess
  1922.         a master key, much less steal one from some other student's
  1923.         pants that you happened to find in a laundry, or even more
  1924.         likely that you are unable to take the key while wearing that
  1925.         dress. However, you're the player, and you're in charge around
  1926.         here, so I'll let you make your own judgments about what's
  1927.         ethical and proper here... ";
  1928.         self.isseen := true;
  1929.     }
  1930.     pass doTake;
  1931.     }
  1932. ;
  1933.  
  1934. hall4: room
  1935.     sdesc = "Hallway"
  1936.     ldesc = "You are in a north-south hallway in the basement. "
  1937.     south = hall2
  1938.     north = hall5
  1939. ;
  1940.  
  1941. hall5: room
  1942.     sdesc = "Hallway"
  1943.     ldesc = "You are at a corner in the basement hallway. You can go east
  1944.      or south. "
  1945.     south = hall4
  1946.     east = hall6
  1947. ;
  1948.  
  1949. hall6: room
  1950.     sdesc = "Hallway"
  1951.     ldesc = "You are at the east end of a basement hallway. To the north is
  1952.      a \"storage room,\" which everyone knows is actually an entrance
  1953.      to the steam tunnels. "
  1954.     west = hall5
  1955.     north = storage
  1956. ;
  1957.  
  1958. storage: room
  1959.     sdesc = "Storage Room"
  1960.     ldesc =
  1961.     {
  1962.         "You are in a large storage room. There really hasn't been
  1963.          anything stored here for a long time (at least, not anything that
  1964.          anybody wants to ever see again). The exit is to the south. To
  1965.      the north lies a door, which is ";
  1966.      if ( tunnelDoor.isopen ) "open"; else "closed"; ". A small card
  1967.      table is sitting in front of the door. ";
  1968.     }
  1969.     south = hall6
  1970.     north =
  1971.     {
  1972.         if ( guard.isActive )
  1973.     {
  1974.         "The guard won't let you enter the tunnel. ";
  1975.             return( nil );
  1976.     }
  1977.     else if ( not tunnelDoor.isopen )
  1978.     {
  1979.         "A closed door stands in your way. ";
  1980.         setit( tunnelDoor );       /* "it" now refers to the closed door */
  1981.         return( nil );
  1982.     }
  1983.     else return( tunnel1 );
  1984.     }
  1985.     enterRoom( actor ) =
  1986.     {
  1987.         if ( guard.isActive )
  1988.     {
  1989.         notify( guard, #patrol, 0 );
  1990.     }
  1991.     pass enterRoom;
  1992.     }
  1993.     leaveRoom( actor ) =
  1994.     {
  1995.         if ( guard.isActive )
  1996.     {
  1997.         unnotify( guard, #patrol );
  1998.     }
  1999.     pass leaveRoom;
  2000.     }
  2001. ;
  2002.  
  2003. tunnelDoor: lockedDoor
  2004.     location = storage
  2005.     mykey = masterKey
  2006. ;
  2007.  
  2008. guard: Actor
  2009.     sdesc = "guard"
  2010.     noun = 'guard' 'him'
  2011.     ldesc =
  2012.     {
  2013.         "The guard is a member of the Kaltech Kops, the elite corps of
  2014.     dedicated men and women that keeps the campus safe from undesirables
  2015.     (i.e., the students). ";
  2016.     if ( not self.isActive )
  2017.         "Currently, the guard is fast asleep, which is quite typical. ";
  2018.     }
  2019.     adjective = 'security'
  2020.     isActive = true
  2021.     location = storage
  2022.     actorDesc =
  2023.     {
  2024.     if ( self.isActive )
  2025.         "A guard is sitting at the card table in front of the door.
  2026.         He watches you carefully, evidently thinking that you might
  2027.         be planning to try to go through the door. ";
  2028.     else
  2029.         "A guard is slumped over a small card table in front of the
  2030.         steam tunnel entrance, evidently fast asleep. How typical. ";
  2031.     }
  2032.     verIoGiveTo( actor ) =
  2033.     {
  2034.         if ( not self.isActive )
  2035.         "The guard appears to be fast asleep. ";
  2036.     }
  2037.     ioGiveTo( actor, dobj ) =
  2038.     {
  2039.         if ( dobj = dollar or dobj = money )
  2040.         "The guard looks at you sternly. \"You should be ashamed of
  2041.         yourself, trying to bribe a member of the elite Kaltech Kops!\"
  2042.         he admonishes you, refusing your offer. ";
  2043.         else if ( dobj <> cup or not cup.isFull )
  2044.         "The guard doesn't appear interested. ";
  2045.     else
  2046.     {
  2047.         self.isActive := nil;
  2048.         unnotify( self, #patrol );
  2049.         "The guard happily accepts your offer; \"ToxiCola! My favorite!\"
  2050.         he says appreciatively, not knowing the evil deed
  2051.         that you have in mind. He quickly drinks the entire cup of
  2052.         ToxiCola. \"Wow! Just the caffeine pickup I needed,\" he says
  2053.         happily.
  2054.         \n\tAfter a few moments, though, he looks rather queasy. \"That
  2055.         caffeine just doesn't last long enough,\" he says just before
  2056.         he passes out, slumping over the card table. ";
  2057.         cup.isFull := nil;
  2058.         toxicola.moveInto( nil );
  2059.         cup.moveInto( cardtable );
  2060.         incscore( 10 );
  2061.     }
  2062.     }
  2063.     patrolMessage =
  2064.     [
  2065.         // random message 1
  2066.     'The guard eyes you warily.'
  2067.     // random message 2
  2068.     'The guard looks at his empty glass, probably wishing he had
  2069.     something to drink.'
  2070.     // random message 3
  2071.     'The guard flips purposefully through the pages of his memo pad.'
  2072.     // random message 4
  2073.     'The guard writes something down on his memo pad, glancing up from
  2074.     time to time to eye you suspiciously.'
  2075.     // random message 5
  2076.     'The guard picks up his empty glass and starts to drink, then
  2077.     realizes it is empty and puts it back down.'
  2078.     ]
  2079.     patrol =
  2080.     {
  2081.         if ( self.location = Me.location )
  2082.     {
  2083.             "\b";
  2084.             say( self.patrolMessage[rand( 5 )]);
  2085.     }
  2086.     }
  2087. ;
  2088.  
  2089. cardtable: fixeditem, surface
  2090.     noun = 'table'
  2091.     adjective = 'card'
  2092.     location = storage
  2093.     sdesc = "card table"
  2094. ;
  2095.  
  2096. emptyglass: container
  2097.     noun = 'glass'
  2098.     adjective = 'empty'
  2099.     sdesc = "empty glass"
  2100.     adesc = "an empty glass"
  2101.     location = cardtable
  2102.     doTake( actor ) =
  2103.     {
  2104.         if ( guard.isActive )
  2105.         "The guard won't let you take the glass. \"Get your own,\"
  2106.         he says. ";
  2107.     else pass doTake;
  2108.     }
  2109.     ioPutIn( actor, dobj ) =
  2110.     {
  2111.         if ( dobj = ln2 ) "The liquid nitrogen evaporates on contact. ";
  2112.     else "It won't fit in the glass. ";
  2113.     }
  2114. ;
  2115.  
  2116. tunnelSounds: function( parm )
  2117. {
  2118.     if ( Me.location.istunnel )
  2119.     {
  2120.         "\b";
  2121.     say( tunnelroom.randomsound[rand( 5 )]);
  2122.     }
  2123.     setfuse( tunnelSounds, rand( 5 ), nil );
  2124. }
  2125.  
  2126. class tunnelroom: room
  2127.     istunnel = true
  2128.     sdesc = "Steam Tunnel"
  2129.     randomsound = [
  2130.     // random sound 1
  2131.       'The rumbling sound suddenly becomes very loud, then, after
  2132.        a few moments, dies down to background levels again.'
  2133.     // random sound 2
  2134.       'A series of clanking noises, like marbles rolling through the
  2135.       steam pipes, starts in the distance, then comes
  2136.       closer and closer, until it seems to pass right overhead. It disappears
  2137.       into the distance.'
  2138.     // random sound 3
  2139.       'A very loud bang suddenly reverberates through the tunnel.'
  2140.     // random sound 4
  2141.       'One of the pipes starts to hiss wildly. After a few moments, it
  2142.       fades back into the background sounds.'
  2143.     // random sound 5
  2144.       'A loud buzzing sound, like an overloaded electrical circuit,
  2145.       emanates from somewhere nearby. After a few moments it is gone.'
  2146.     ]
  2147. ;
  2148.  
  2149. tunnelpipes: fixeditem
  2150.     sdesc = "pipes"
  2151.     noun = 'pipe' 'pipes'
  2152.     ldesc = "The pipes range from very small copper tubes only an inch around
  2153.      to huge asbestos-covered cylinders over two feet in diameter.  Many of
  2154.      the larger pipes are marked \"STEAM - 300 PSI.\" "
  2155.     locationOK = true
  2156.     location =
  2157.     {
  2158.         if ( Me.location.istunnel ) return( Me.location );
  2159.     else return( nil );
  2160.     }
  2161. ;
  2162.  
  2163. tunnel1: tunnelroom
  2164.     ldesc = "You are in a steam tunnel. It is very hot and dry in here.
  2165.      The place has a strange musty odor; the air is very still, but there
  2166.      are distant sounds of all sorts that vibrate through the pipes. The
  2167.      pipes all seem to be hissing quietly, and a low rumbling sound constantly
  2168.      reverberates through the tunnel. Occasionally a distant clang or thud
  2169.      or crack emanates from the pipes.
  2170.      \n\tThe steam tunnel runs east and west. A small passage leads south. "
  2171.     east = tunnel2
  2172.     west = tunnel3
  2173.     south = storage
  2174.     enterRoom( actor ) =
  2175.     {
  2176.         if ( not self.isseen ) setfuse( tunnelSounds, rand( 5 ), nil );
  2177.     pass enterRoom;
  2178.     }
  2179. ;
  2180.  
  2181. tunnel2: tunnelroom
  2182.     ldesc = "You are at the east end of the steam tunnel. "
  2183.     west = tunnel1
  2184. ;
  2185.  
  2186. tunnelStorage: room
  2187.     sdesc = "Storage Room"
  2188.     ldesc = "You are in a small storage room. The exit lies north. "
  2189.     north = tunnel13
  2190. ;
  2191.  
  2192. tunnel3: tunnelroom
  2193.     ldesc = "You are in an east-west section of the steam tunnels. "
  2194.     east = tunnel1
  2195.     west = tunnel4
  2196. ;
  2197.  
  2198. tunnel4: tunnelroom
  2199.     ldesc = "You are at a T-intersection of two sections of steam
  2200.      tunnel; tunnels go off to the north, south, and east. "
  2201.     east = tunnel3
  2202.     north = tunnel5
  2203.     south = tunnel6
  2204. ;
  2205.  
  2206. darktunnel: darkroom, tunnelroom
  2207.     controlon = nil
  2208.     islit =
  2209.     {
  2210.         if ( self.controlon ) return( true );
  2211.     else pass islit;
  2212.     }
  2213. ;
  2214.  
  2215. tunnel5: darktunnel
  2216.     ldesc = "You are at a corner in the steam tunnel: you can go
  2217.      west and south. "
  2218.     west = tunnel7
  2219.     south = tunnel4
  2220. ;
  2221.  
  2222. tunnel6: tunnelroom
  2223.     ldesc = "You are at a corner in the steam tunnel: you can go
  2224.      west and north. "
  2225.     west = tunnel8
  2226.     north = tunnel4
  2227. ;
  2228.  
  2229. tunnel7: darktunnel
  2230.     ldesc = "You are in an east-west section of the steam tunnel.
  2231.      A very small passage between some steam pipes leads north, but
  2232.      it would be a tight squeeze. "
  2233.     east = tunnel5
  2234.     west = tunnel9
  2235.     north =
  2236.     {
  2237.         return(crawltest( tunnel12,
  2238.          'You lay down on one of the pipes and start to snake
  2239.           through the passage. For a moment, you think you\'re
  2240.           stuck, but you manage to wriggle your way through. You
  2241.           emerge on the north side of the narrow crawl.' ));
  2242.     }
  2243. ;
  2244.  
  2245. tunnel8: tunnelroom
  2246.     controlon = true
  2247.     ldesc =
  2248.     {
  2249.         "You are in an east-west section of the steam tunnel. On the
  2250.          wall is a control unit. ";
  2251.     if ( not self.controlon )
  2252.     {
  2253.         "It is quite dark in this section of the tunnel; the only
  2254.          illumination is coming from the control unit's display";
  2255.          
  2256.         if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2257.          and flashlight.islit )
  2258.             " (and from the flashlight, of course)";
  2259.     
  2260.         ". ";
  2261.     }
  2262.     }
  2263.     east = tunnel6
  2264.     west = tunnel10
  2265. ;
  2266.  
  2267. controlunit: fixeditem
  2268.     sdesc = "control unit"
  2269.     noun = 'unit'
  2270.     adjective = 'control'
  2271.     location = tunnel8
  2272.     ldesc =
  2273.     {
  2274.         "The control unit is quite modern and high-tech looking, in
  2275.          stark contrast to the tunnels around it. It consists of a keypad
  2276.          which allows entry of arbitrary numbers, a large green button,
  2277.      and a display screen. The unit is labelled \"Station 2.\" ";
  2278.     controldisp.ldesc;
  2279.     }
  2280.     objref =
  2281.     {
  2282.         local l;
  2283.     
  2284.     l := self.value;
  2285.     
  2286.     if ( l = 322 ) return( tunnel8 );
  2287.     else if ( l = 612 ) return( mazeroom );
  2288.     else if ( l = 293 ) return( darktunnel );
  2289.     else return( nil );
  2290.     }
  2291.     value = 322
  2292. ;
  2293.  
  2294. controlpad: fixeditem
  2295.     sdesc = "keypad"
  2296.     noun = 'keypad' 'pad'
  2297.     adjective = 'key'
  2298.     location = tunnel8
  2299.     ldesc = "It's one of those cheesy membrane keypads, like on a microwave
  2300.      oven or the new Enterprise's control panels. It allows you to type numbers
  2301.      made up of digits from 0 to 9. "
  2302.     verIoTypeOn( actor ) = {}
  2303.     ioTypeOn( actor, dobj ) =
  2304.     {
  2305.         if ( dobj <> numObj )
  2306.         "The keypad only allows entry of numbers. ";
  2307.     else
  2308.     {
  2309.         "As you type the number sequence, the display screen is
  2310.         updated. ";
  2311.         controlunit.value := numObj.value;
  2312.         controldisp.ldesc;
  2313.     }
  2314.     }
  2315. ;
  2316.  
  2317. controlbutton: buttonitem
  2318.     sdesc = "button"
  2319.     adjective = 'green'
  2320.     location = tunnel8
  2321.     doPush( actor ) =
  2322.     {
  2323.         local r;
  2324.     
  2325.     r := controlunit.objref;
  2326.     if ( r )
  2327.     {
  2328.         "The display is updated as you press the button. ";
  2329.         r.controlon := not r.controlon;
  2330.         controldisp.ldesc;
  2331.         if ( r = tunnel8 )
  2332.         {
  2333.             "The lights in the tunnel ";
  2334.             if ( r.controlon )
  2335.             "come on. ";
  2336.         else
  2337.         {
  2338.             "go out, leaving only the display screen's light ";
  2339.             if (( flashlight.isIn( Me ) or flashlight.isIn( tunnel8 ))
  2340.              and flashlight.islit )
  2341.                 "(and the flashlight, of course) ";
  2342.             "for illumination. ";
  2343.         }
  2344.         }
  2345.     }
  2346.     else "The unit beeps; nothing else appears to happen. ";
  2347.     }
  2348. ;
  2349.  
  2350. controldisp: fixeditem
  2351.     sdesc = "display screen"
  2352.     noun = 'screen'
  2353.     adjective = 'display'
  2354.     location = tunnel8
  2355.     ldesc =
  2356.     {
  2357.         local l, r;
  2358.     
  2359.     l := controlunit.value;
  2360.     r := controlunit.objref;
  2361.         "The screen is currently displaying: \""; say( l ); ": ";    
  2362.     if ( r )
  2363.     {
  2364.         if ( r.controlon ) "ON"; else "OFF";
  2365.     }
  2366.     else "???";
  2367.     
  2368.     "\". ";
  2369.     }
  2370. ;
  2371.  
  2372. tunnel9: darktunnel
  2373.     ldesc = "You are at a corner in the steam tunnel.  You can go east
  2374.      or south. "
  2375.     east = tunnel7
  2376.     south = tunnel11
  2377. ;
  2378.  
  2379. tunnel10: tunnelroom
  2380.     ldesc = "You are at a corner in the steam tunnel. You can go east
  2381.      or north. "
  2382.     east = tunnel8
  2383.     north = tunnel11
  2384. ;
  2385.  
  2386. tunnel11: tunnelroom
  2387.     ldesc = "You are in a north-south section of the steam tunnels. Set
  2388.      into one wall is a large chute. "
  2389.     north = tunnel9
  2390.     south = tunnel10
  2391. ;
  2392.  
  2393. chute: fixeditem, container
  2394.     sdesc = "chute"
  2395.     noun = 'chute'
  2396.     location = tunnel11
  2397.     ldesc = "The chute is large enough for anything you're carrying,
  2398.      but not nearly big enough for you. You can't tell where it goes,
  2399.      except down. "
  2400.     ioPutIn( actor, dobj ) =
  2401.     {
  2402.         "You put "; dobj.thedesc; " into the chute, and it slides away
  2403.     into the darkness. After a few moments, you hear a soft thud. ";
  2404.     dobj.moveInto( chuteroom );
  2405.     }
  2406. ;
  2407.  
  2408. crawltest: function( rm, msg )
  2409. {
  2410.     local i;
  2411.     
  2412.     i := 1;
  2413.     while ( i <= length( Me.contents ))
  2414.     {
  2415.         if ( not Me.contents[i].iscrawlable )
  2416.     {
  2417.         "You'll never get through carrying ";
  2418.         Me.contents[i].thedesc; ". ";
  2419.         return( nil );
  2420.     }
  2421.         i := i + 1;
  2422.     }
  2423.     say( msg ); "\b";
  2424.     return( rm );
  2425. }
  2426.  
  2427. tunnel12: tunnelroom
  2428.     ldesc =
  2429.     {
  2430.         if ( self.isseen )
  2431.             "You are in an east-west section of the steam tunnels. A narrow
  2432.             passage between some steam pipes might allow you to go south. ";
  2433.     else
  2434.         "You are in another steam tunnel, but this one is substantially
  2435.         different from the tunnels you have been in so far. This tunnel
  2436.         is much wider, less cluttered; it looks like it was built more
  2437.         recently than the south tunnels. The tunnel itself runs east
  2438.         and west, and passing back to the south is evidently possible,
  2439.         given your presence here. ";
  2440.     }
  2441.     east = tunnel13
  2442.     west = pitTop
  2443.     south =
  2444.     {
  2445.         return(crawltest( tunnel7, 'Going through the crawl
  2446.      southbound is just as difficult as it was coming north,
  2447.      you observe.' ));
  2448.     }
  2449. ;
  2450.  
  2451. tunnel13: tunnelroom
  2452.     ldesc = "You are at the east end of a steam tunnel. A passage leads
  2453.      north, and another one leads south. "
  2454.     west = tunnel12
  2455.     north = maze0
  2456.     south = tunnelStorage
  2457. ;
  2458.  
  2459. maze0: room
  2460.     sdesc = "Outside Maze"
  2461.     ldesc =
  2462.     {
  2463.         "You are in a small room, with exits north and south. The
  2464.          passage to the north has a small sign reading \"Behavior Lab Maze\";
  2465.          the room is filled with strange equipment, which you surmise is
  2466.          connected in some way to the maze. ";
  2467.      
  2468.     if ( mazeroom.controlon )
  2469.         "The equipment is buzzing loudly. Standing
  2470.          near it makes you feel vaguely dizzy. ";
  2471.     
  2472.     if ( not self.isseen )
  2473.     {
  2474.         "\n\tYou sigh in resignation as you realize that you have reached
  2475.         the obligatory Adventure Game Maze, and ";
  2476.         if ( mazeview.isseen )
  2477.             "wish that this were a graphical adventure, so your trip to
  2478.         the maze viewing room had resulted in a map you could refer
  2479.         to now. Fortunately, you do recall noting that the passages
  2480.         in the maze all lead east-west or north-south. ";
  2481.             else
  2482.             "wonder what this maze's unique twist will be. Surely, it
  2483.         won't just be a boring old labyrinth... ";
  2484.     }
  2485.     }
  2486.     south = tunnel13
  2487.     north = maze1
  2488. ;
  2489.  
  2490. mazeequip: decoration
  2491.     noun = 'equipment' 'coil' 'coils' 'pipe' 'pipes' 'wire' 'wires'
  2492.     adjective = 'electric' 'electrical'
  2493.     sdesc = "equipment"
  2494.     location = maze0
  2495.     ldesc =
  2496.     {
  2497.         "The equipment resembles some of the particle accelerators that
  2498.     you have seen. It has several huge electric coils, all arranged
  2499.     around a series of foot-diameter pipes. A tangled web of enormous
  2500.     wires connects various parts of the equipment together and other
  2501.     wires feed it power. ";
  2502.     
  2503.         if ( mazeroom.controlon )
  2504.         "The equipment is buzzing loudly. Standing near it makes
  2505.         you feel vaguely dizzy. ";
  2506.     }
  2507. ;
  2508.  
  2509. mazeroom: room
  2510.     controlon = true
  2511.     sdesc = "Lost in the Maze"
  2512.     lookAround( verbosity ) =
  2513.     {
  2514.         self.statusLine;
  2515.     self.nrmLkAround( self.controlon ? true : verbosity );
  2516.     }
  2517.     ldesc =
  2518.     {
  2519.         if ( self.controlon )
  2520.         "You can't quite seem to get your bearings. There are some
  2521.         passages leading away, but you can't quite tell how many or
  2522.         in which direction they leads. ";
  2523.     else
  2524.     {
  2525.         local cnt, tot, i;
  2526.         
  2527.         tot := 0;
  2528.         i := 1;
  2529.         while ( i <= 4 )
  2530.         {
  2531.             if ( self.dirlist[i] ) tot := tot + 1;
  2532.             i := i + 1;
  2533.         }
  2534.  
  2535.         "You are in a room in the maze; they all look alike.
  2536.         You can go ";
  2537.         
  2538.         i := 1;
  2539.         cnt := 0;
  2540.         while ( i <= 4 )
  2541.         {
  2542.             if ( self.dirlist[i] )
  2543.         {
  2544.             if ( cnt > 0 )
  2545.             {
  2546.                 if ( tot = 2 ) " and ";
  2547.             else if ( cnt+1 = tot ) ", and ";
  2548.             else ", ";
  2549.             }
  2550.             cnt := cnt + 1;
  2551.             
  2552.             say( ['north' 'south' 'east' 'west'][i] );
  2553.         }
  2554.             i := i + 1;
  2555.         }
  2556.         ". ";
  2557.     }
  2558.     }
  2559.     mazetravel( rm ) =
  2560.     {
  2561.         if ( self.controlon )
  2562.     {
  2563.         local r;
  2564.         
  2565.         "You can't figure out which direction is which; the more you
  2566.         stumble about, the more the room seems to spin around. After a
  2567.         few steps, you're not sure if you've actually gone anywhere,
  2568.         since all these rooms look alike...\b";
  2569.         
  2570.         /*
  2571.          *   We know we can only go one of four directions, but generate
  2572.          *   a random number up to 6; if we generate 5 or 6, we won't go
  2573.          *   anywhere, but we won't let on that this is the case.
  2574.          */
  2575.         r := rand( 6 );
  2576.         
  2577.         /*
  2578.          *   Note that we want to confuse the player in active-maze mode
  2579.          *   as much as possible, so we don't want any clues as to whether
  2580.          *   there was any travel in this direction or not.  So, return
  2581.          *   "self" rather than "nil," since we won't get any message if
  2582.          *   we return "nil," but we'll get the current room's message if
  2583.          *   we return "self;" since all the messages are the same, this
  2584.          *   won't provide any information.
  2585.          */
  2586.         if ( r < 5 )
  2587.         {
  2588.             r := self.dirlist[ r ];
  2589.         if ( r ) return( r );
  2590.         else return( self );
  2591.         }
  2592.         else return( self );
  2593.     }
  2594.     else
  2595.     {
  2596.         if ( rm )
  2597.             return( rm );
  2598.         else
  2599.         {
  2600.             "You can't go that way. ";
  2601.             return( nil );
  2602.         }
  2603.     }
  2604.     }
  2605.     north = ( self.mazetravel( self.dirlist[1] ))
  2606.     south = ( self.mazetravel( self.dirlist[2] ))
  2607.     east = ( self.mazetravel( self.dirlist[3] ))
  2608.     west = ( self.mazetravel( self.dirlist[4] ))
  2609.     up = ( self.mazetravel( 0 ))
  2610.     down = ( self.mazetravel( 0 ))
  2611.     in = ( self.mazetravel( 0 ))
  2612.     out = ( self.mazetravel( 0 ))
  2613.     ne = ( self.mazetravel( 0 ))
  2614.     nw = ( self.mazetravel( 0 ))
  2615.     se = ( self.mazetravel( 0 ))
  2616.     sw = ( self.mazetravel( 0 ))
  2617. ;
  2618.  
  2619. maze1: mazeroom
  2620.     dirlist = [ 0 maze0 maze2 0 ]
  2621. ;
  2622.  
  2623. maze2: mazeroom
  2624.     dirlist = [ maze9 0 maze3 maze1 ]
  2625. ;
  2626.  
  2627. maze3: mazeroom
  2628.     dirlist = [ maze8 0 maze4 maze2 ]
  2629. ;
  2630.  
  2631. maze4: mazeroom
  2632.     dirlist = [ 0 0 maze5 maze3 ]
  2633. ;
  2634.  
  2635. maze5: mazeroom
  2636.     dirlist = [ maze6 0 0 maze4 ]
  2637. ;
  2638.  
  2639. maze6: mazeroom
  2640.     dirlist = [ 0 maze5 0 maze7 ]
  2641. ;
  2642.  
  2643. maze7: mazeroom
  2644.     dirlist = [ maze30 0 maze9 maze8 ]
  2645. ;
  2646.  
  2647. maze8: mazeroom
  2648.     dirlist = [ maze29 maze3 maze7 0 ]
  2649. ;
  2650.  
  2651. maze9: mazeroom
  2652.     dirlist = [ 0 maze2 0 maze10 ]
  2653. ;
  2654.  
  2655. maze10: mazeroom
  2656.     dirlist = [ 0 0 maze9 maze11 ]
  2657. ;
  2658.  
  2659. maze11: mazeroom
  2660.     dirlist = [ 0 maze35 maze10 maze12 ]
  2661. ;
  2662.  
  2663. maze12: mazeroom
  2664.     dirlist = [ 0 0 maze11 0 ]
  2665. ;
  2666.  
  2667. maze13: mazeroom
  2668.     dirlist = [ maze24 maze18 0 0 ]
  2669. ;
  2670.  
  2671. maze14: mazeroom
  2672.     dirlist = [ 0 maze17 0 maze15 ]
  2673. ;
  2674.  
  2675. maze15: mazeroom
  2676.     dirlist = [ 0 maze16 maze14 0 ]
  2677. ;
  2678.  
  2679. maze16: mazeroom
  2680.     dirlist = [ maze15 maze23 maze17 0 ]
  2681. ;
  2682.  
  2683. maze17: mazeroom
  2684.     dirlist = [ maze14 maze22 maze18 maze16 ]
  2685. ;
  2686.  
  2687. maze18: mazeroom
  2688.     dirlist = [ maze13 maze21 0 maze17 ]
  2689. ;
  2690.  
  2691. maze19: mazeroom
  2692.     dirlist = [ 0 maze20 maze35 0 ]
  2693. ;
  2694.  
  2695. maze20: mazeroom
  2696.     dirlist = [ maze19 0 0 maze21 ]
  2697. ;
  2698.  
  2699. maze21: mazeroom
  2700.     dirlist = [ maze18 0 maze20 0 ]
  2701. ;
  2702.  
  2703. maze22: mazeroom
  2704.     dirlist = [ maze17 0 0 0 ]
  2705. ;
  2706.  
  2707. maze23: mazeroom
  2708.     dirlist = [ maze16 0 0 0 ]
  2709. ;
  2710.  
  2711. maze24: mazeroom
  2712.     dirlist = [ 0 maze13 maze25 0 ]
  2713. ;
  2714.  
  2715. maze25: mazeroom
  2716.     dirlist = [ maze33 0 maze26 maze24 ]
  2717. ;
  2718.  
  2719. maze26: mazeroom
  2720.     dirlist = [ maze32 0 0 maze25 ]
  2721. ;
  2722.  
  2723. maze27: mazeroom
  2724.     dirlist = [ maze31 0 0 0 ]
  2725. ;
  2726.  
  2727. maze28: mazeroom
  2728.     dirlist = [ 0 0 maze29 0 ]
  2729. ;
  2730.  
  2731. maze29: mazeroom
  2732.     dirlist = [ 0 maze8 maze30 maze28 ]
  2733. ;
  2734.  
  2735. maze30: mazeroom
  2736.     dirlist = [ 0 maze7 0 maze29 ]
  2737. ;
  2738.  
  2739. maze31: mazeroom
  2740.     dirlist = [ 0 maze27 0 maze32 ]
  2741. ;
  2742.  
  2743. maze32: mazeroom
  2744.     dirlist = [ 0 maze26 maze31 0 ]
  2745. ;
  2746.  
  2747. maze33: mazeroom
  2748.     dirlist = [ 0 maze25 0 maze34 ]
  2749. ;
  2750.  
  2751. maze34: mazeroom
  2752.     dirlist = [ 0 0 maze33 mazeStart ]
  2753. ;
  2754.  
  2755. maze35: mazeroom
  2756.     dirlist = [ maze11 0 0 maze19 ]
  2757. ;
  2758.  
  2759. mazeStart: room
  2760.     sdesc = "Start of Maze"
  2761.     ldesc = "You are at the start of the maze. A passage into the
  2762.      maze is to the east, and a heavy one-way door marked \"Exit\" is to the
  2763.      south. "
  2764.     east = maze34
  2765.     south = behaviorLab
  2766. ;
  2767.  
  2768. mazedoor: fixeditem
  2769.     sdesc = "door"
  2770.     noun = 'door'
  2771.     adjective = 'exit' 'one-way' 'heavy'
  2772.     verDoOpen( actor ) = { "No need; just walk on through. "; }
  2773.     location = mazeStart
  2774. ;
  2775.  
  2776. chuteroom: room
  2777.     sdesc = "Chute Room"
  2778.     ldesc = "You are in a small room with exits to the northwest
  2779.      and south. The bottom of a large chute opens into the room. "
  2780.     nw = pitBottom
  2781.     south = shiproom
  2782. ;
  2783.  
  2784. chute2: fixeditem, container
  2785.     sdesc = "chute"
  2786.     noun = 'chute'
  2787.     location = chuteroom
  2788.     ioPutIn( actor, dobj ) =
  2789.     {
  2790.         "This is the bottom of the chute; you can't put objects
  2791.     into it. ";
  2792.     }
  2793. ;
  2794.  
  2795. pitTop: tunnelroom
  2796.     sdesc = "Top of Pit"
  2797.     ldesc =
  2798.     {
  2799.         "You are in a large open area in the steam tunnels. In
  2800.          the center of the room is a large pit, around which is a protective
  2801.          railing. A steam tunnel is to the east. ";
  2802.     if ( rope.tieItem = railing )
  2803.         "A rope is tied to the railing, and extends down into the pit. ";
  2804.     }
  2805.     east = tunnel12
  2806.     down =
  2807.     {
  2808.         if ( rope.tieItem = railing )
  2809.     {
  2810.         "You climb down the rope...\b";
  2811.         return( pitBottom );
  2812.     }
  2813.     else
  2814.     {
  2815.         "You'd probably break your neck if you tried to jump
  2816.         into the pit. ";
  2817.             return( nil );
  2818.     }
  2819.     }
  2820. ;
  2821.  
  2822. tieVerb: deepverb
  2823.     sdesc = "tie"
  2824.     verb = 'tie'
  2825.     prepDefault = toPrep
  2826.     ioAction( toPrep ) = 'TieTo'
  2827. ;
  2828.  
  2829. railing: fixeditem
  2830.     sdesc = "rail"
  2831.     noun = 'rail' 'railing'
  2832.     location = pitTop
  2833.     verIoTieTo( actor ) = {}
  2834.     ioTieTo( actor, dobj ) =
  2835.     {
  2836.         "You tie one end of the rope to the railing, and lower the other
  2837.     end into the pit. It appears to extend to the bottom of the pit. ";
  2838.     rope.tieItem := self;
  2839.     rope.moveInto( pitTop );
  2840.     rope.isfixed := true;
  2841.     }
  2842. ;
  2843.  
  2844. climbupVerb: deepverb
  2845.     verb = 'climb up'
  2846.     sdesc = "climb up"
  2847.     doAction = 'Climbup'
  2848. ;
  2849.  
  2850. climbdownVerb: deepverb
  2851.     verb = 'climb down'
  2852.     sdesc = "climb down"
  2853.     doAction = 'Climbdown'
  2854. ;
  2855.  
  2856. rope: item
  2857.     sdesc = "rope"
  2858.     isListed = ( not self.isfixed )
  2859.     noun = 'rope'
  2860.     location = tunnelStorage
  2861.     ldesc =
  2862.     {
  2863.         if ( self.tieItem )
  2864.     {
  2865.         "It's tied to "; self.tieItem.thedesc; ". ";
  2866.     }
  2867.     else pass ldesc;
  2868.     }
  2869.     verDoTieTo( actor, io ) =
  2870.     {
  2871.         if ( self.tieItem )
  2872.     {
  2873.         "It's already tied to "; self.tieItem.thedesc; "! ";
  2874.     }
  2875.     }
  2876.     doTake( actor ) =
  2877.     {
  2878.         if ( self.tieItem )
  2879.     {
  2880.         "(You untie it first, of course.) ";
  2881.         self.tieItem := nil;
  2882.         self.isfixed := nil;
  2883.     }
  2884.     pass doTake;
  2885.     }
  2886.     verDoClimb( actor ) =
  2887.     {
  2888.         if ( self.tieItem = nil )
  2889.         "Climbing down the rope in its present configuration would
  2890.         get you nowhere. ";
  2891.     }
  2892.     doClimb( actor ) =
  2893.     {
  2894.         "You climb down the rope...\b";
  2895.         Me.travelTo( pitBottom );
  2896.     }
  2897.     verDoClimbdown( actor ) = {}
  2898.     doClimbdown( actor ) = { self.doClimb( actor ); }
  2899. ;
  2900.  
  2901. pitBottom: room
  2902.     sdesc = "Huge Cavern"
  2903.     ldesc = "You are in a huge and obviously artificial cavern. The cave
  2904.      has apparently been dug out over a long period of time; some parts
  2905.      look very old, and other areas look comparatively recent. A small bronze
  2906.      plaque affixed to one of the older walls reads, \"Great Undergraduate
  2907.      Excavation - 1982.\"
  2908.      From high above, a small opening in
  2909.      the ceiling casts a dim glow over the vast chamber. A rope extends
  2910.      from the opening above. Passages of various ages lead north, south,
  2911.      east, west, southeast, and southwest. "
  2912.     up =
  2913.     {
  2914.         "It's a long climb, but you somehow manage it.\b";
  2915.         return( pitTop );
  2916.     }
  2917.     se = chuteroom
  2918.     east = biohall1
  2919.     south = bank
  2920.     north = cave
  2921.     sw = insOffice
  2922.     west = machineshop
  2923. ;
  2924.  
  2925. pitplaque: fixeditem, readable
  2926.     noun = 'plaque'
  2927.     sdesc = "bronze plaque"
  2928.     adjective = 'bronze' 'small'
  2929.     location = pitBottom
  2930.     ldesc = "Great Undergraduate Excavation\n\t\t\t1982"
  2931. ;
  2932.  
  2933. insOffice: room
  2934.     sdesc = "Insurance Office"
  2935.     ldesc =
  2936.     {
  2937.         "You are in an insurance office. Like most insurance offices,
  2938.     the area is rather non-descript. The exit is northeast. ";
  2939.     if ( not self.isseen )
  2940.     {
  2941.         "\n\tAs you walk into the office, a large metallic robot, very
  2942.         much like the traditional sci-fi film robot, but wearing a dark
  2943.         polyester business suit, zips up to you. \"Hi, I'm Lloyd the
  2944.         Friendly Insurance Robot,\" he says in a mechanical British
  2945.         accent. \"You look like you could use some insurance! Here, let
  2946.         me prepare a policy for you.\"
  2947.         \n\tLloyd scurries around the room, gathering papers and
  2948.         studying charts, occasionally zipping up next to you and
  2949.         measuring your height and other dimensions, making all kinds
  2950.         of notes, and generally scampering about. After a few minutes,
  2951.         he comes up to you, showing you a piece of paper.
  2952.         \n\t\"I have the perfect policy for you. Just one dollar will
  2953.         buy you a hundred thousand worth of insurance!\" He watches
  2954.         you anxiously. ";
  2955.         
  2956.         notify( lloyd, #offerins, 0 );
  2957.     }
  2958.     }
  2959.     ne = pitBottom
  2960.     out = pitBottom
  2961. ;
  2962.  
  2963. /*
  2964.  *   Lloyd the Friendly Insurance Robot is a full-featured actor. He will
  2965.  *   initially just wait in his office until paid for a policy, but will
  2966.  *   thereafter follow the player around relentlessly.  Lloyd doesn't
  2967.  *   interact much, though; he just hangs around and does wacky things.
  2968.  */
  2969. lloyd: Actor
  2970.     noun = 'lloyd' 'him'
  2971.     sdesc = "Lloyd"
  2972.     adesc = "Lloyd"
  2973.     thedesc = "Lloyd"
  2974.     ldesc = "Lloyd the Friendly Insurance Robot is a strange combination
  2975.      of the traditional metallic robot and an insurance salesman; over his
  2976.      bulky metal frame is a polyester suit. "
  2977.     actorAction( v, d, p, i ) =
  2978.     {
  2979.         if ( v = helloVerb )
  2980.         "\"Hello,\" Lloyd responds cheerfully. ";
  2981.     else if ( v = followVerb and d = Me )
  2982.     {
  2983.         if ( self.offering )
  2984.             "\"Sorry, but I must stay here until I've made a sale.\" ";
  2985.         else
  2986.             "\"I will follow you,\" Lloyd says. \"That will allow me
  2987.         to pay any claim you make immediately should the need arise.
  2988.         It's just one of the ways we keep our overhead so low.\" ";
  2989.     }
  2990.     else
  2991.         "\"I'm sorry, that's not in your policy.\" ";
  2992.     exit;
  2993.     }
  2994.     verDoAskAbout( actor, io ) = {}
  2995.     doAskAbout( actor, io ) =
  2996.     {
  2997.         if ( io = policy )
  2998.         "\"Your policy perfectly fits your needs, according to my
  2999.         calculations,\" Lloyd says. \"I'm afraid it's much too
  3000.         complicated to go into in any detail right now, but you have
  3001.         my assurances that you won't be disappointed.\" ";
  3002.     else
  3003.         "\"I'm afraid I don't know much about that,\" Lloyd says
  3004.         apologetically. ";
  3005.     }
  3006.     actorDesc =
  3007.     {
  3008.         if ( self.offering )
  3009.         "Lloyd is here, offering you an insurance policy for only
  3010.         one dollar. ";
  3011.     else
  3012.         "Lloyd the Friendly Insurance Robot is here. ";
  3013.     }
  3014.     offering = true
  3015.     offermsg =
  3016.     [
  3017.         'Lloyd waits patiently for you to make up your mind about the
  3018.      insurance policy.'
  3019.     'Lloyd watches you expectantly, hoping you will buy the insurance
  3020.      policy.'
  3021.     'Lloyd shows you the insurance policy again. "Only a dollar," he
  3022.      says.'
  3023.     'Lloyd looks at you intently. "What can I do to make you buy this
  3024.      insurance policy right now?" he asks rhetorically.'
  3025.     'Lloyd reviews the policy to make sure it looks just right, and
  3026.      offers it to you again.'
  3027.     ]
  3028.     offerins =
  3029.     {
  3030.         if ( self.location = Me.location )
  3031.     {
  3032.         "\b";
  3033.         say(self.offermsg[rand( 5 )]);
  3034.     }
  3035.     }
  3036.     followmsg =
  3037.     [
  3038.         'Lloyd watches attentively to make sure you don\'t hurt yourself.'
  3039.     'Lloyd hums one of his favorite insurance songs.'
  3040.     'Lloyd gets out some actuarial tables and does some computations.'
  3041.     'Lloyd looks through his papers.'
  3042.     'Lloyd checks the area to make sure it\'s safe.'
  3043.     ]
  3044.     follow =
  3045.     {
  3046.         if ( Me.location = machinestorage ) return;
  3047.     
  3048.     "\b";
  3049.         if ( self.location <> Me.location )
  3050.     {
  3051.         if ( Me.location = railcar )
  3052.             "Lloyd hops into the railcar, showing remarkable agility
  3053.         for such a large mechanical device. ";
  3054.         else if ( self.location = railcar )
  3055.             "Lloyd hops out of the railcar. ";
  3056.         else if ( Me.location = pitTop and self.location = pitBottom )
  3057.             "Amazingly, Lloyd scrambles up the rope and joins you. ";
  3058.         else if ( Me.location = pitBottom and self.location = pitTop )
  3059.             "Lloyd descends smoothly down the rope and joins you. ";
  3060.         else if (( Me.location = tunnel7 and self.location = tunnel12 )
  3061.          or ( Me.location = tunnel12 and self.location = tunnel7 ))
  3062.             "Somehow, Lloyd manages to squeeze through the crawl. ";
  3063.         else if ( Me.location = quad )
  3064.             "Lloyd follows you. When he sees the apparent radioactive
  3065.         waste spill, he is quite alarmed. After a moment, though,
  3066.         he deduces that the spill is a staged part of the Ditch Day
  3067.         festivities, and he calms down. ";
  3068.         else if ( Me.location = storage )
  3069.             "Lloyd enters the storage room. Upon seeing the guard, he
  3070.             rolls over and starts giving his insurance pitch. After a
  3071.         moment, he notices the guard is unconscious. \"It's just as
  3072.         well,\" Lloyd confides; \"security work is awfully risky, and
  3073.         his rates would have been quite high.\" ";
  3074.         else
  3075.             "Lloyd follows you. ";
  3076.         
  3077.         self.moveInto( Me.location );
  3078.     }
  3079.     else
  3080.     {
  3081.         say(self.followmsg[rand( 5 )]);
  3082.     }
  3083.     }
  3084.     verIoGiveTo( actor ) = {}
  3085.     ioGiveTo( actor, dobj ) =
  3086.     {
  3087.         if ( dobj = dollar )
  3088.         self.doPay( actor );
  3089.     else if ( dobj = darbcard )
  3090.         "Lloyd looks at you apologetically. \"So sorry, I must insist
  3091.         on cash,\" he says. ";
  3092.     else
  3093.         "Lloyd doesn't appear interested. ";
  3094.     }
  3095.     verDoPay( actor ) = {}
  3096.     doPay( actor ) =
  3097.     {
  3098.         if ( not self.offering )
  3099.     {
  3100.         "Lloyd looks at you, confused. \"I've already sold you all
  3101.         the insurance you need!\" ";
  3102.     }
  3103.         else if ( dollar.isIn( actor ))
  3104.     {
  3105.         "Lloyd graciously accepts the payment, and hands you a copy
  3106.         of your policy. \"You might wonder how we keep costs so low,\"
  3107.         Lloyd says. \"It's simple: we're highly automated, which keeps
  3108.         labor costs low; I run the whole company, which keeps the
  3109.         bureaucratic overhead low; and, most importantly, I follow you
  3110.         everywhere you go for the duration of the policy, ensuring that
  3111.         you're paid on the spot should anything happen, which means we
  3112.         don't have to waste money investigating claims!\" ";
  3113.         
  3114.         unnotify( self, #offerins );
  3115.         notify( self, #follow, 0 );
  3116.         dollar.moveInto( nil );
  3117.         policy.moveInto( Me );
  3118.         self.offering := nil;
  3119.     }
  3120.     else
  3121.     {
  3122.         "You don't have any money with which to pay Lloyd. ";
  3123.     }
  3124.     }
  3125.     location = insOffice
  3126. ;
  3127.  
  3128. policy: readable
  3129.     sdesc = "insurance policy"
  3130.     adesc = "an insurance policy"
  3131.     iscrawlable = true
  3132.     noun = 'policy'
  3133.     adjective = 'insurance'
  3134.     location = lloyd
  3135.     ldesc =
  3136.     {
  3137.         "The insurance policy lists the payment schedule for hundreds
  3138.     of types of injuries; the list is far too lengthy to go into in any
  3139.     detail here, but rest assured, ";
  3140.     if ( lloyd.offering )
  3141.         "it looks like an excellent deal. ";
  3142.     else
  3143.         "you're highly satisified with what you
  3144.         got for your dollar. You feel extremely well protected. ";
  3145.     }
  3146. ;
  3147.  
  3148. machineshop: room
  3149.     sdesc = "Machine Shop"
  3150.     ldesc = "You are in the machine shop. It appears that this huge
  3151.      chamber was once used to build and maintain the equipment that
  3152.      was used to create the Great Undergraduate Excavation.  Though
  3153.      most of the equipment is gone now, one very large and strange
  3154.      machine dominates the center of the room.
  3155.      The exit is east, and a small passage leads north. "
  3156.     east = pitBottom
  3157.     out = pitBottom
  3158.     north = machinestorage
  3159. ;
  3160.  
  3161. machine: fixeditem
  3162.     sdesc = "machine"
  3163.     noun = 'machine'
  3164.     location = machineshop
  3165.     ldesc = "The machine is unlike anything you've seen before; it's not
  3166.      at all clear what its purpose is. The only feature that looks like it
  3167.      might do anything useful is a large red button labelled \"DANGER!\" "
  3168. ;
  3169.  
  3170. machinebutton: buttonitem
  3171.     location = machineshop
  3172.     sdesc = "red button"
  3173.     adjective = 'red'
  3174.     doPush( actor ) =
  3175.     {
  3176.         "As you push the button, the machine starts making horrible noises
  3177.     and flinging huge metal rods in all directions. Enormous clouds of
  3178.     smoke rise from the machine as it flails about. After a few minutes
  3179.     of this behavior, you think to step back from the machine.  You're
  3180.     not fast enough, though; before you can escape it, a stray metal
  3181.     bar flings itself against your thumb, creating a sensation not unlike
  3182.     intense pain. ";
  3183.     
  3184.         if ( lloyd.location = self.location )
  3185.     {
  3186.         "\n\t";
  3187.             if ( self.isscored )
  3188.             "Lloyd looks at you apologetically. \"I don't want to sound
  3189.         patronizing, but you knew it would do that. I'm afraid I can't
  3190.         accept a claim for that injury, as it was effectively
  3191.         self-inflicted.\" He looks at you sadly. \"I do sympathize,
  3192.         though. That must be quite painful,\" he understates. ";
  3193.         else
  3194.         {
  3195.             self.isscored := true;
  3196.         "Lloyd rolls over and looks at your thumb. \"That looks
  3197.         awful,\" he says as you jump about, holding your thumb.
  3198.         Lloyd produces a thick pile of paper and starts leafing
  3199.         through it. \"Temporary loss of use of one thumb... ah,
  3200.         yes, here it is. That injury pays five dollars.\" Lloyd puts
  3201.         away his papers and produces a crisp new five dollar bill,
  3202.         which you accept (with your other hand). ";
  3203.         money.moveInto( Me );
  3204.         }
  3205.     }
  3206.     }
  3207. ;
  3208.  
  3209. machinestorage: darkroom
  3210.     sdesc = "Storage Closet"
  3211.     ldesc = "You are in a small storage closet off the machine shop.
  3212.      The exit is south. "
  3213.     south = machineshop
  3214.     out = machineshop
  3215. ;
  3216.  
  3217. happygear: treasure
  3218.     location = machinestorage
  3219.     noun = 'gear'
  3220.     adjective = 'mr.' 'mr' 'happy' 'mister'
  3221.     sdesc = "Mr.\ Happy Gear"
  3222.     thedesc = "Mr.\ Happy Gear"
  3223.     adesc = "Mr.\ Happy Gear"
  3224.     ldesc = "It's an ordinary gear, about an inch in diameter; the only
  3225.      notable feature is that it has holes cut in such a manner that it
  3226.      looks like a happy face. "
  3227. ;
  3228.  
  3229. bank: room
  3230.     sdesc = "Bank"
  3231.     ldesc = "You're in what was once the Great Undergraduate Excavation's
  3232.      bank. It doesn't appear to get much use any more. The exit is north,
  3233.      and a small passage leads south. "
  3234.     north = pitBottom
  3235.     south = bankvault
  3236.     out = pitBottom
  3237. ;
  3238.  
  3239. bankvault: room
  3240.     sdesc = "Vault Room"
  3241.     ldesc = "The feature dominating this room is the bank's safe.
  3242.      The only exit is north. "
  3243.     north = bank
  3244.     out = bank
  3245. ;
  3246.  
  3247. banksafe: fixeditem, openable
  3248.     sdesc = "safe"
  3249.     noun = 'safe' 'door' 'vault'
  3250.     location = bankvault
  3251.     isopen = nil
  3252.     ldesc =
  3253.     {
  3254.         if ( self.isblasted )
  3255.     {
  3256.         "The safe looks as though it has suffered some sort of
  3257.         intense trauma lately; the door is just barely hanging on
  3258.         its hinges, leaving the contents of the safe quite exposed. ";
  3259.         pass ldesc;
  3260.     }
  3261.     else
  3262.     {
  3263.         "The safe is huge, like the type you might find in a bank.
  3264.         The only notable features are a huge metal door (quite closed),
  3265.         and a large slot labelled \"Night Deposit Slot.\" ";
  3266.     }
  3267.     }
  3268.     doOpen( actor ) =
  3269.     {
  3270.         if ( self.isblasted ) pass doOpen;
  3271.     else
  3272.         "You can't open such a secure safe without resorting
  3273.          to some sort of drastic action. ";
  3274.     }
  3275. ;
  3276.  
  3277. darbcard: treasure
  3278.     sdesc = "DarbCard"
  3279.     noun = 'darbcard' 'card'
  3280.     adjective = 'darb'
  3281.     location = banksafe
  3282. ;
  3283.  
  3284. bankslot: fixeditem, container
  3285.     sdesc = "night deposit slot"
  3286.     noun = 'slot'
  3287.     adjective = 'night' 'deposit'
  3288.     location = bankvault
  3289.     ldesc = "The slot is very large, big enough to put a large sack of
  3290.      money into. Unfortunately, you won't have much luck extracting anything
  3291.      from the slot, since it has been carefully constructed to allow items
  3292.      to enter, but not leave. "
  3293.     ioPutIn( actor, dobj ) =
  3294.     {
  3295.         "\^<< dobj.thedesc >> disappears into the deposit slot. ";
  3296.     dobj.moveInto( banksafe );
  3297.     }
  3298. ;
  3299.  
  3300. cave: room
  3301.     sdesc = "Tunnel"
  3302.     ldesc = "You're in a north-south tunnel. The tunnel slopes steeply
  3303.      downward to the north. "
  3304.     north = railway1
  3305.     down = railway1
  3306.     south = pitBottom
  3307.     up = pitBottom
  3308. ;
  3309.  
  3310. railway1: room
  3311.     sdesc = "Subway Station"
  3312.     ldesc = "You're in a very large musty chamber deep underground. In the
  3313.      center of the room is a small rail car. Strangely, the car is sitting on
  3314.      the floor; there are no rails under the car, or, indeed, in the station
  3315.      at all. You look around, and notice about three meters up the east wall
  3316.      is a round tunnel. A passage leads south. "
  3317.     south = cave
  3318.     destination = railway2
  3319.     tunneltime = 3
  3320.     east =
  3321.     {
  3322.         "The tunnel is too high up the wall. You won't be able to enter
  3323.     it without benefit of the railcar. ";
  3324.         return( nil );
  3325.     }
  3326. ;
  3327.  
  3328. class rtunnel: fixeditem
  3329.     sdesc = "tunnel"
  3330.     noun = 'tunnel'
  3331.     verDoEnter( actor ) = {}
  3332.     doEnter( actor ) =
  3333.     {
  3334.         railway1.east;
  3335.     }
  3336. ;
  3337.  
  3338. rtunnel1: rtunnel
  3339.     location = railway1
  3340. ;
  3341.  
  3342. rtunnel2: rtunnel
  3343.     location = railway2
  3344. ;
  3345.  
  3346. railway2: room
  3347.     sdesc = "Subway Station"
  3348.     ldesc = "You're in a subway station. About three meters up the west
  3349.      wall is a tunnel; a passage (at ground level) leads south. A railcar
  3350.      is sitting on the floor in the center of the room. "
  3351.     south = computercenter
  3352.     destination = railway1
  3353.     tunneltime = 3
  3354.     west =
  3355.     {
  3356.         "The tunnel is too high up the wall. You won't be able to enter
  3357.     it without benefit of the railcar. ";
  3358.         return( nil );
  3359.     }
  3360. ;
  3361.  
  3362. computercenter: room
  3363.     sdesc = "Computer Center"
  3364.     ldesc = "You're in a computer room. Unfortunately, all the equipment
  3365.      here is hopelessly out of date and doesn't interest you in the least.
  3366.      The exit is north. "
  3367.     north = railway2
  3368. ;
  3369.  
  3370. compequip: decoration
  3371.     sdesc = "computer equipment"
  3372.     noun = 'equipment'
  3373.     adjective = 'computer'
  3374.     location = computercenter
  3375.     ldesc = "The equipment is all very outdated. It's not the least bit
  3376.      interesting. "
  3377. ;
  3378.  
  3379. randombook: treasure, readable
  3380.     sdesc = "book"
  3381.     ldesc = "The book is entitled \"A Million Random Digits.\" In flipping
  3382.      through the book, you find that it is, in fact, a million random digits,
  3383.      nicely tabulated and individually numbered from 0 to 999,999 (computer
  3384.      people always start numbering at 0). "
  3385.     noun = 'book' 'digits'
  3386.     adjective = 'million' 'random' 'digits' 'numbers'
  3387.     location = computercenter
  3388. ;
  3389.  
  3390. railtunnel: room
  3391.     sdesc = "Tunnel"
  3392.     ldesc = "The tunnel is rather non-descript. "
  3393. ;
  3394.  
  3395. railcar: vehicle, fixeditem, container
  3396.     location = railway1
  3397.     isdroploc = true        // stuff dropped while on board ends up in railcar
  3398.     sdesc = "rail car"
  3399.     noun = 'car' 'railcar'
  3400.     adjective = 'rail'
  3401.     ldesc =
  3402.     {
  3403.         "This is a small rail car, big enough for a couple of people.
  3404.          It has a small control panel, which consists of a green button,
  3405.      a gauge, and a small hole labelled \"Coolant.\" ";
  3406.      if ( funnel.location = railhole )
  3407.         "The hole seems to contain a funnel. ";
  3408.      railmeter.ldesc;
  3409.     }
  3410.     travel =
  3411.     {
  3412.         if ( self.location <> railtunnel )
  3413.     {
  3414.         "\bThe car rises to about three meters off the floor. It then
  3415.         starts to accelerate toward the tunnel, and plunges into the
  3416.         tunnel with a rush of air. ";
  3417.         self.destination := self.location.destination;
  3418.         self.tunneltime := self.location.tunneltime;
  3419.         self.moveInto( railtunnel );
  3420.     }
  3421.     else if ( self.tunneltime > 0 )
  3422.     {
  3423.         "\bThe car races down the tunnel at terrifying speed. ";
  3424.         self.tunneltime := self.tunneltime - 1;
  3425.     }
  3426.     else
  3427.     {
  3428.         "\bThe car starts to decelerate sharply. After a few more seconds,
  3429.         it emerges into a station and glides to a halt. It slowly
  3430.         descends to the ground; once settled, the hum of its engine
  3431.         gradually disappears. ";
  3432.         self.isActive := nil;
  3433.         self.moveInto( self.destination );
  3434.         unnotify( self, #travel );
  3435.     }
  3436.     }
  3437.     checkunboard =
  3438.     {
  3439.         if ( self.isActive )
  3440.     {
  3441.         "Please wait until the railcar has come to a complete and
  3442.         final stop, and the captain has turned off the \"Fasten Seat
  3443.         Belt\" sign. (Actually, I made up the part about the \"Fasten
  3444.         Seat Belt\" sign, but you'll have to wait until the car
  3445.         has stopped nonetheless.) ";
  3446.         return( nil );
  3447.     }
  3448.     else return( true );
  3449.     }
  3450.     out =
  3451.     {
  3452.         if ( self.checkunboard ) pass out;
  3453.     else return( nil );
  3454.     }
  3455.     doUnboard( actor ) =
  3456.     {
  3457.         if ( self.checkunboard ) pass doUnboard;
  3458.     }
  3459. ;
  3460.  
  3461. railmeter: fixeditem
  3462.     location = railcar
  3463.     sdesc = "gauge"
  3464.     noun = 'gauge' 'meter'
  3465.     ldesc =
  3466.     {
  3467.         "The gauge is not labelled with any units you recognize, but
  3468.      the arc is divided into regions colored green, yellow, and red. The
  3469.      needle is currently in the ";
  3470.         if ( railcar.iscooled ) "green"; else "red";
  3471.     " section of the scale. ";
  3472.     }
  3473. ;
  3474.  
  3475. railhole: fixeditem, container
  3476.     location = railcar
  3477.     sdesc = "hole"
  3478.     noun = 'hole'
  3479.     adjective = 'coolant'
  3480.     ldesc =
  3481.     {
  3482.         if ( funnel.location = self )
  3483.         "A funnel is in the hole. ";
  3484.         else if ( railcar.iscooled )
  3485.         "Wisps of water vapor rise from the hole. ";
  3486.     else
  3487.         "The hole is labelled \"Coolant.\" It's about an inch
  3488.         or so in diameter. ";
  3489.     }
  3490.     verIoPourIn( actor ) = {}
  3491.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  3492.     ioPutIn( actor, dobj ) =
  3493.     {
  3494.         if ( dobj = funnel )
  3495.     {
  3496.         "A perfect fit! ";
  3497.         funnel.moveInto( self );
  3498.     }
  3499.     else if ( dobj = ln2 )
  3500.     {
  3501.         if ( funnel.location = self )
  3502.         {
  3503.             if ( railcar.iscooled )
  3504.             "It's already full of liquid nitrogen! ";
  3505.         else
  3506.         {
  3507.             "You carefully pour the liquid nitrogen into the
  3508.             funnel.  It doesn't take very much before the tank
  3509.             is full. ";
  3510.             railcar.iscooled := true;
  3511.         }
  3512.         }
  3513.         else
  3514.         {
  3515.             "The hole is too small; most if not all of the liquid
  3516.         nitrogen you pour spills all around, rather than into
  3517.         the hole. ";
  3518.         }
  3519.     }
  3520.     else
  3521.     {
  3522.         "It won't fit in the hole. ";
  3523.     }
  3524.     }
  3525. ;
  3526.  
  3527. railbutton: buttonitem
  3528.     location = railcar
  3529.     sdesc = "green button"
  3530.     adjective = 'green'
  3531.     doPush( actor ) =
  3532.     {
  3533.         if ( Me.location <> railcar )
  3534.     {
  3535.         "Get in the railcar first. ";
  3536.     }
  3537.     else if ( railcar.isbroken )
  3538.     {
  3539.         "Nothing happens. ";
  3540.     }
  3541.     else if ( railcar.isActive )
  3542.     {
  3543.         "Nothing happens. Perhaps this is because you have
  3544.         already pushed the button quite recently. ";
  3545.     }
  3546.         else if ( railcar.iscooled )
  3547.     {
  3548.         "A low-frequency hum sounds from within the railcar. After
  3549.         a few moments, it starts to levitate off the track. ";
  3550.         notify( railcar, #travel, 0 );
  3551.         railcar.isActive := true;
  3552.     }
  3553.     else
  3554.     {
  3555.         "A low-frequency hum sounds from within the railcar. It grows
  3556.         in strength, and soon starts to vibrate the whole car. You smell
  3557.         the familiar odor of burning electronic components. Suddenly,
  3558.         a bright light flashes underneath the railcar, a cloud of thick
  3559.         black smoke rises, and the humming stops. It appears you have
  3560.         toasted the railcar. ";
  3561.         railcar.isbroken := true;
  3562.     }
  3563.     }
  3564. ;
  3565.  
  3566. biohall1: room
  3567.     sdesc = "Hall"
  3568.     ldesc = "You are in an east-west hallway. A passage labelled \"Bio Lab\"
  3569.      leads south. "
  3570.     west = pitBottom
  3571.     east = biohall2
  3572.     south = biolab
  3573. ;
  3574.  
  3575. biolab: room
  3576.     sdesc = "Bio Lab"
  3577.     ldesc =
  3578.     {
  3579.         "You are in the Biology Lab. All sorts of strange equipment is
  3580.     scattered around the room. A lab bench is in the center of the room,
  3581.     and on one wall is a cabinet (which is ";
  3582.     if ( biocabinet.isopen ) "open"; else "closed";
  3583.     "). A passage leads north. ";
  3584.     }
  3585.     north = biohall1
  3586. ;
  3587.  
  3588. bioEquipment: decoration
  3589.     sdesc = "strange equipment"
  3590.     noun = 'equipment'
  3591.     adjective = 'strange'
  3592.     location = biolab
  3593.     ldesc = "The equipment is entirely unfamiliar to you. "
  3594. ;
  3595.  
  3596. biobench: fixeditem, surface
  3597.     noun = 'bench'
  3598.     adjective = 'lab'
  3599.     sdesc = "lab bench"
  3600.     location = biolab
  3601.     ldesc =
  3602.     {
  3603.         "The bench is topped with one of those strange black rubber surfaces
  3604.     that seemingly all scientific lab benches have. ";
  3605.     pass ldesc;
  3606.     }
  3607. ;
  3608.  
  3609. funnel: container
  3610.     sdesc = "funnel"
  3611.     noun = 'funnel'
  3612.     location = biobench
  3613.     ioPutIn( actor, dobj ) =
  3614.     {
  3615.         if ( dobj = ln2 )
  3616.     {
  3617.         if ( self.location = railhole or self.location = bottle )
  3618.             self.location.ioPutIn( actor, dobj );
  3619.         else
  3620.             "The liquid nitrogen pours through the funnel, lands
  3621.         nowhere in particular, and evaporates. ";
  3622.     }
  3623.     else
  3624.     {
  3625.         "It wouldn't accomplish anything to put ";
  3626.         dobj.thedesc; " into the funnel. ";
  3627.     }
  3628.     }
  3629.     ldesc =
  3630.     {
  3631.         if ( self.location = bottle or self.location = railhole )
  3632.     {
  3633.         "The funnel is stuck into "; self.location.adesc; ". ";
  3634.     }
  3635.     else
  3636.         "It's a normal white plastic funnel, about six inches
  3637.         across at its wide end and about half an inch at its
  3638.         narrow end. ";
  3639.     }
  3640.     verIoPourIn( actor ) = {}
  3641.     ioPourIn( actor, dobj ) = { self.ioPutIn( actor, dobj ); }
  3642. ;
  3643.  
  3644. biohall2: room
  3645.     sdesc = "Hall"
  3646.     ldesc =
  3647.     {
  3648.         "You are at the east end of an east-west hallway. A doorway
  3649.      leads east. ";
  3650.     if ( not self.isseen )
  3651.     {
  3652.         notify( biocreature, #menace, 0 );
  3653.     }
  3654.     }
  3655.     west = biohall1
  3656.     east =
  3657.     {
  3658.         if ( biocreature.location = self )
  3659.     {
  3660.         if ( slime.location = nil )
  3661.         {
  3662.             "The creature grabs you and pushes you back, depositing
  3663.         a huge glob of slime on you in the process. ";
  3664.         slime.moveInto( Me );
  3665.         slime.isworn := true;
  3666.         }
  3667.             else "The creature won't let you pass. ";
  3668.         return( nil );
  3669.     }
  3670.     else return( biooffice );
  3671.     }
  3672. ;
  3673.  
  3674. slime: clothingItem
  3675.     noun = 'glob' 'slime'
  3676.     sdesc = "glob of slime"
  3677.     doWear( actor ) =
  3678.     {
  3679.         "No, thank you. ";
  3680.     }
  3681. ;
  3682.  
  3683. biocreature: Actor
  3684.     location = biohall2
  3685.     sdesc = "creature"
  3686.     noun = 'creature'
  3687.     ldesc = "It looks like the result of a biological experiment that
  3688.       failed (or succeeded, depending on who performed the experiment). "
  3689.     actorDesc = "An enormous creature is blocking the hallway to the east.
  3690.       He (please don't press for details as to how you know, but \"he\"
  3691.       is the appropriate pronoun here) appears to be part human, but
  3692.       exactly what part is not clear. The creature's leathery skin is
  3693.       a bright green, and is largely covered with a thick transluscent
  3694.       slime. "
  3695.     menaceMessage =
  3696.     [
  3697.         'The creature roars a huge roar in your general direction.'
  3698.     'The creature menaces you.'
  3699.     'In a tender moment, the creature produces a magazine and opens up
  3700.      the centerfold. He looks longingly at the picture. After a few
  3701.      moments, he notices you again, and puts away the magazine; as he\'s
  3702.      putting it away, you see that it\'s a copy of "Playmutant."'
  3703.     'The creature looks at you warily.'
  3704.     'The creature growls at you, showing his enormous pointy fangs.'
  3705.     ]
  3706.     menace =
  3707.     {
  3708.         if ( self.location = Me.location )
  3709.     {
  3710.             "\b";
  3711.             say( self.menaceMessage[rand( 5 )]);
  3712.     }
  3713.     }
  3714. ;
  3715.  
  3716. biooffice: room
  3717.     sdesc = "Bio Office"
  3718.     ldesc = "You are in the Biology Office. A large desk dominates the
  3719.      room. The exit is west. "
  3720.     west = biohall2
  3721. ;
  3722.  
  3723. biodesk: fixeditem, surface
  3724.     noun = 'desk'
  3725.     adjective = 'large'
  3726.     location = biooffice
  3727.     sdesc = "desk"
  3728. ;
  3729.  
  3730. biocabinet: openable, fixeditem
  3731.     noun = 'cabinet'
  3732.     location = biolab
  3733.     sdesc = "cabinet"
  3734.     isopen = nil
  3735. ;
  3736.  
  3737. class chemitem: item
  3738.     location = biocabinet
  3739.     noun = 'chemical'
  3740.     plural = 'chemicals'
  3741.     adesc = { "some "; self.sdesc; }
  3742.     ldesc =
  3743.     {
  3744.         "It's a small lump of goo. The only identification is
  3745.          a label reading \""; self.sdesc; ".\" ";
  3746.     }
  3747. ;
  3748.     
  3749. gfxq3: chemitem
  3750.     noun = 'GF-XQ3'
  3751.     sdesc = "GF-XQ3"
  3752. ;
  3753.  
  3754. gfxq9: chemitem
  3755.     noun = 'GF-XQ9'
  3756.     sdesc = "GF-XQ9"
  3757. ;
  3758.  
  3759. polyred: chemitem
  3760.     noun = 'red'
  3761.     adjective = 'poly'
  3762.     sdesc = "Poly Red"
  3763. ;
  3764.  
  3765. polyblue: chemitem
  3766.     noun = 'blue'
  3767.     adjective = 'poly'
  3768.     sdesc = "Poly Blue"
  3769. ;
  3770.  
  3771. compoundT99: chemitem
  3772.     noun = 't99'
  3773.     adjective = 'compound'
  3774.     sdesc = "Compound T99"
  3775. ;
  3776.  
  3777. compoundT30: chemitem
  3778.     noun = 't30'
  3779.     adjective = 'compound'
  3780.     sdesc = "Compound T30"
  3781. ;
  3782.  
  3783. clonemaster: container
  3784.     noun = 'master' 'clonemaster'
  3785.     adjective = 'clone'
  3786.     location = biobench
  3787.     sdesc = "CloneMaster"
  3788.     ldesc =
  3789.     {
  3790.         "The CloneMaster is a simple machine. It consists of a button
  3791.     marked \"Clone,\" and a small receptacle. ";
  3792.      clonerecept.ldesc;
  3793.     }
  3794.     ioPutIn( actor, dobj ) = { clonerecept.ioPutIn( actor, dobj ); }
  3795.     verDoTakeOut( actor, io ) = { clonerecept.verIoTakeOut( actor, io ); }
  3796. ;
  3797.  
  3798. clonerecept: fixeditem, container
  3799.     sdesc = "receptacle"
  3800.     noun = 'receptacle'
  3801.     location = clonemaster
  3802.     ldesc =
  3803.     {
  3804.         "The receptacle is somewhat like that of a kitchen blender. ";
  3805.         pass ldesc;
  3806.     }
  3807. ;
  3808.  
  3809. clonebutton: buttonitem
  3810.     sdesc = "clone button"
  3811.     adjective = 'clone'
  3812.     doPush( actor ) =
  3813.     {
  3814.         if ( slime.location = clonerecept )
  3815.     {
  3816.         "The CloneMaster clicks and whirs for several seconds. ";
  3817.         if ( gfxq3.location = clonerecept and
  3818.          polyblue.location = clonerecept and
  3819.          compoundT99.location = clonerecept
  3820.          and length( clonerecept.contents ) = 4 )
  3821.         {
  3822.             "A monstrous female version (again, don't ask how you know
  3823.          it's female) leaps from the tiny machine";
  3824.             if ( Me.location = biocreature.location )
  3825.         {
  3826.             ". The two monsters look at each other with passion in
  3827.             their mutant eyes. They run to each other with open arms,
  3828.             seemingly in slow motion. They embrace, engage in some
  3829.             mushy behavior, and then run away together to elope. ";
  3830.             biocreature.moveInto( nil );
  3831.             unnotify( biocreature, #menace );
  3832.         }
  3833.         else
  3834.             ", looks around, and, seeing nothing of
  3835.             interest, runs off. ";
  3836.         }
  3837.         else
  3838.             "An exact duplicate of the monstrous creature whose slime
  3839.         you placed in the CloneMaster leaps forth from the tiny
  3840.         machine. He looks at you menacingly for a moment, then
  3841.         runs off into the distance, never to be seen again. ";
  3842.         
  3843.         slime.moveInto( nil );
  3844.     }
  3845.     else "Nothing happens. ";
  3846.     }
  3847.     location = clonemaster
  3848. ;
  3849.  
  3850. omega: treasure
  3851.     sdesc = "Great Seal of the Omega"
  3852.     noun = 'seal' 'omega' 'stamp'
  3853.     adjective = 'great' 'rubber'
  3854.     location = biodesk
  3855.     ldesc = "The Great Seal is a large rubber stamp, about an inch and
  3856.      a half square. The stamp consists of a large circle that is filled by a
  3857.      giant capital omega, under which is the word \"Approved.\" Around the
  3858.      outside of the circle, the words \"The Great Seal of the Omega\" are
  3859.      inscribed. "
  3860. ;
  3861.  
  3862. rope2: fixeditem
  3863.     sdesc = "rope"
  3864.     noun = 'rope'
  3865.     location = pitBottom
  3866.     ldesc = "The rope extends from the opening in the ceiling high above. "
  3867.     verDoTake( actor ) =
  3868.     {
  3869.         "The rope seems to be tied to something from above (which would
  3870.     probably explain why it's extending up to the ceiling in the
  3871.     first place, you deduce in a rare moment of lucid thinking). ";
  3872.     }
  3873.     verDoClimbup( actor ) = {}
  3874.     doClimbup( actor ) = { self.doClimb( actor ); }
  3875.     verDoClimb( actor ) = {}
  3876.     doClimb( actor ) =
  3877.     {
  3878.         "It's a long climb, but you somehow manage it.\b";
  3879.     Me.travelTo( pitTop );
  3880.     }
  3881. ;
  3882.